Fragen zu enable_if-Ausdruck



  • Hallo,

    ich lese grad ein bisschen über die SFINAE-Unterstützung vom VS2015 und bin dabei auf das folgende Bsp. gestoßen:

    #include <type_traits>
    
    template<typename T, std::enable_if_t<std::is_integral<T>{}> * = nullptr>
    char f(T *);
    
    template<typename T>
    short f(...);
    
    int main()
    {
        static_assert(sizeof(f<int>(nullptr)) == sizeof(char), "fail");
        static_assert(sizeof(f<int *>(nullptr)) == sizeof(short), "fail");
    }
    

    Ich verstehe dabei den enable_if_t-Ausdruck im ersten Template nicht richtig, und wollte fragen, ob mir das jemand erklären kann.

    std::is_integral<T> ergibt einen Typ, die "{}" dahinter erzeugen doch eine Instanz von dem Typ und den übergebe ich als ersten Parameter an das enable_if, was ein bool erwartet? Wie passt das zusammen? Es müsste doch irgendwie ein "true" oder "false" an enable_if übergeben werden? Mit "is_integral_v" hätte ich es verstanden, weil das gibt ja ein "contexpr bool" zurück, aber so wie da dasteht, kapier ich das nicht.

    VG

    Pellaeon



  • In der CPP-Referenz zu is_integral steht:

    Checks whether T is an integral type. Provides the member constant value which is equal to true, if T is the type bool, char, char16_t, char32_t, wchar_t, short, int, long, long long, or any implementation-defined extended integer types, including any signed, unsigned, and cv-qualified variants. Otherwise, value is equal to false.



  • Provides the member constant value which is equal to true

    "value" wird oben ja eben nicht verwendet. Mit value wäre die Sache klar.



  • Ich denke, das ist was du suchst:

    Member functions (Inherited from integral_constant):

    operator bool
    Returns value (public member function )



  • In dem Ausdruck oben steht doch nur

    std::is_integral<T>{}
    

    Also der Typ gefolgt von "{}". Letzteres erzeugt das Objekt, ein Aufruf von Operator () findet doch hier nicht statt?



  • Überfordere mich nicht 😉 Ich lerne ja erst noch C++, aber das führt alles zum selben Ergebnis:

    // integral_constant::operator value_type example
    #include <iostream>
    #include <type_traits>
    
    int main() {
      // is_integral<T> inherits from integral_constant
    
      if ( std::is_integral<int>() )
        std::cout << "int is an integral type" << std::endl;
    
      if ( std::is_integral<int>{} )
        std::cout << "int is an integral type" << std::endl;
    
      // same result as:
      if ( std::is_integral<int>::value )
        std::cout << "int is an integral type" << std::endl;
    
      return 0;
    }
    

    http://www.cplusplus.com/reference/type_traits/integral_constant/
    http://www.cplusplus.com/reference/type_traits/integral_constant/operator%20value_type/

    Ein Stichwort wäre dann vielleicht noch "braced initialization"...



  • Es gibt einen constexpr cast-Operator nach value (=bool) für std::is_integral. Das funktioniert also:

    constexpr bool a = std::is_integral<short*>{};
    	constexpr bool b = std::is_integral<short>{};
    


  • manni66 schrieb:

    Es gibt einen constexpr cast-Operator nach value (=bool) für std::is_integral. Das funktioniert also:

    constexpr bool a = std::is_integral<short*>{};
    	constexpr bool b = std::is_integral<short>{};
    

    Ah ok, danke 🙂

    @temin: ich wollte ja nicht wissen, ob es funktioniert, sondern warum 😃



  • Pellaeon schrieb:

    @temin: ich wollte ja nicht wissen, ob es funktioniert, sondern warum 😃

    Steht das nicht so im ersten meiner beiden Links?

    Accessible as member integral_constant::value, or through type casting.


  • Mod

    casting \neq conversion.


Anmelden zum Antworten