bestimmte Typen von Template ausschließen



  • @It0101 sagte in bestimmte Typen von Template ausschließen:

    Der einzige Unterschied ist, dass es jetzt in einer cpp liegt und vorher in einem Header....

    @manni66 sagte in bestimmte Typen von Template ausschließen:

    @It0101 sagte in bestimmte Typen von Template ausschließen:

    Die genaue Fehlermeldung ist:
    multiple definition of `foobar[abi:cxx11](char const*)'|

    Es fehlt einfach inline?



  • Danke dir 🙂 daran lag es. Und ich Holzkopf dachte, ich hätte die std::enable_if - Geschichte vermurkst 😃



  • komischerweise bekommt er die Spezialisierung für "double" nicht hin....

    
    #include <string>
    
    template <typename T>
    class FoobarClass
    {
    public:
        FoobarClass( T &&val_ ) :
            Value( std::move( val_ ) )
        {
        }
    
    private:
        T Value;
    };
    
    template <typename T, typename std::enable_if <!std::is_pointer<T>::value, T>::type = 0>
    FoobarClass<T> foobar( T value )
    {
        FoobarClass<T> result( std::move( value ) );
        return std::move( result );
    }
    
    int main()
    {
        auto dummy = foobar( double( 17 ) );
        return 0;
    }
    

    'std::enable_if<true, double>::type {aka double}' is not a valid type for a template non-type parameter|



  • std::enable_if ist mir viel zu kompliziert:

    #include <string>
    
    template <typename T>
    class FoobarClass
    {
    public:
        FoobarClass( T &&val_ ) :
            Value( std::move( val_ ) )
        {
        }
    
    private:
        T Value;
    };
    
    template <typename T>
    FoobarClass<T> foobar( T value )
    {
        if constexpr( !std::is_pointer_v<T> ) {
          FoobarClass<T> result( std::move( value ) );
          return std::move( result );
       }
    }
    
    int main()
    {
        auto dummy = foobar( double( 17 ) );
        return 0;
    }
    

    g++ -Wall -Wextra -pedantic -std=c++17 templ.cpp -o templ
    templ.cpp: In Funktion »int main()«:
    templ.cpp:27:10: Warnung: Variable »dummy« gesetzt, aber nicht verwendet [-Wunused-but-set-variable]
    27 | auto dummy = foobar( double( 17 ) );
    | ^~~~~
    templ.cpp: In Instanziierung von »FoobarClass<T> foobar(T) [mit T = double]«:
    templ.cpp:27:39: von hier erfordert
    templ.cpp:21:32: Warnung: das Verschieben eines lokalen Objekts in einer return-Anweisung verhindert das Einsparen der Kopie [-Wpessimizing-move]
    21 | return std::move( result );
    | ^
    templ.cpp:21:32: Anmerkung: entfernen Sie den Aufruf von »std::move«

    Beachte die move Warnung!



  • Was die Warnung angeht: Ich weiß. Ich bin nur immer misstrauisch, weil kein Schwein RVO garantieren kann, oder seh ich das falsch?

    Deine Variante funzt.
    Mich wundert nur, dass er beim Aufruf mit "const char*" z.B. die korrekt "alternative" Funktion verwendet und nicht das template. Denn die Template-Funktion wird ja durchaus für const char* erzeugt, nur sie hat eben keinen Inhalt, oder habe ich da was falsch verstanden?



  • @It0101 sagte in bestimmte Typen von Template ausschließen:

    Was die Warnung angeht. Ich weiß. Ich bin nur immer misstrauisch, weil kein Schwein RVO garantieren kann, oder seh ich das falsch?

    RVO ist garantiert, NRVO (noch) nicht, aber von alles Compilern implementiert.



  • Guter Hinweis. In dem Fall vertraue ich dann doch lieber der RVO 😃



  • @It0101 sagte in bestimmte Typen von Template ausschließen:

    Denn die Template-Funktion wird ja durchaus für const char* erzeugt, nur sie hat eben keinen Inhalt, oder habe ich da was falsch verstanden?

    Ja, es wird aber die besser passende Funktion verwendet.

    Wenn du die Funktion tatsächlich nur auf passende Typen beschränken willst/musst, helfen Concepts:

    template <typename T>
    requires !std::is_pointer_v<T>
    FoobarClass<T> foobar( T value )
    {
          FoobarClass<T> result( std::move( value ) );
          return result;
    }
    

    Alternativ, wenn nicht verfügbar, sollt es auch

    template<class T> struct dependent_false : std::false_type {};
    template <typename T>
    FoobarClass<T> foobar( T value )
    {
        if constexpr( !std::is_pointer_v<T> ) {
          FoobarClass<T> result( std::move( value ) );
          return result;
       }
        else
           static_assert(dependent_false<T>::value, "Geht nicht"); 
    }
    

    tun. hier geklaut

    Oder du musst doch std::enable_if richtig verstehen 😉



  • Ich habe es jetzt übrigens hinbekommen, ohne "Concepts" den Typ T zu einzuschränken:

    // Ganzzahlige Datentypen und Gleitkomma-Datentypen aber keine Zeichen ( 8Bit )
    template <typename T, 
                       typename = std::enable_if_t<(std::is_integral<T>::value || 
                                             std::is_floating_point<T>::value ) &&
                                             !( std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value ||
                                             std::is_same<T, unsigned char>::value || std::is_same<T, char>::value ||
                                             std::is_same<T, signed char>::value )>>
     void operator>> ( T & );
    

    Ist natürlich ein ganz schöner Hauklotz, aber typsicher 😃



  • @It0101 sagte in bestimmte Typen von Template ausschließen:

    Ich habe es jetzt übrigens hinbekommen, ohne "Concepts" den Typ T zu einzuschränken:

    // Ganzzahlige Datentypen und Gleitkomma-Datentypen aber keine Zeichen ( 8Bit )
    template <typename T, 
                       typename = std::enable_if_t<(std::is_integral<T>::value || 
                                             std::is_floating_point<T>::value ) &&
                                             !( std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value ||
                                             std::is_same<T, unsigned char>::value || std::is_same<T, char>::value ||
                                             std::is_same<T, signed char>::value )>>
     void operator>> ( T & );
    

    Ist natürlich ein ganz schöner Hauklotz, aber typsicher 😃

    Ab C++17 darfst Du auch _v verwenden und das ::value weglassen.

    // Ganzzahlige Datentypen und Gleitkomma-Datentypen aber keine Zeichen ( 8Bit )
    template <typename T, 
       typename = std::enable_if_t<
          (std::is_integral_v<T> || std::is_floating_point_v<T>) &&
          !(
              std::is_same_v<T, uint8_t> || std::is_same_v<T, int8_t> ||
              std::is_same_v<T, unsigned char> || std::is_same_v<T, char> ||
              std::is_same_v<T, signed char>
           )
       >
    >
    void operator>> (T&);
    

Log in to reply