2012-08-13 13 views
10

He escrito el siguiente código para tratar de detectar si un tipo tiene una variable de miembro estática. Lamentablemente, siempre está volviendo que la variable no existe.sfinae busca miembro estático usando decltype

¿Podría alguien decirme dónde me está yendo mal? Estoy usando g ++ 4.7.1.

#include <iostream> 
#include <utility> 
#include <type_traits> 

using namespace std; 

template <class T>             
class has_is_baz               
{                 
    template<class U, 
      typename std::enable_if<std::is_same<bool, decltype(U::is_baz)>::value>::type...>      
     static std::true_type check(int);       
    template <class>             
     static std::false_type check(...);       
public:                
    static constexpr bool value = decltype(check<T>(0))::value;  
}; 

struct foo { }; 

struct bar 
{ 
    static constexpr bool is_baz = true; 
}; 

int main() 
{ 
    cout << has_is_baz<foo>::value << '\n'; 
    cout << has_is_baz<bar>::value << '\n'; 
} 

Respuesta

8

El problema principal era que:

std::is_same<bool, decltype(bar::is_baz)>::value == false 

Luego, su SFINAE siempre estaba fallando. He reescrito el rasgo has_is_baz y ahora funciona:

#include <iostream> 
#include <utility> 
#include <type_traits> 

using namespace std; 

template <class T>             
class has_is_baz               
{  
    template<class U, class = typename std::enable_if<!std::is_member_pointer<decltype(&U::is_baz)>::value>::type> 
     static std::true_type check(int); 
    template <class> 
     static std::false_type check(...); 
public: 
    static constexpr bool value = decltype(check<T>(0))::value; 
}; 

struct foo { }; 

struct bar 
{ 
    static constexpr bool is_baz = true; 
}; 

struct not_static { 
    bool is_baz; 
}; 

int main() 
{ 
    cout << has_is_baz<foo>::value << '\n'; 
    cout << has_is_baz<bar>::value << '\n'; 
    cout << has_is_baz<not_static>::value << '\n'; 
} 

demostración here.

Editar: He corregido el rasgo de tipo. Como @litb indicó, estaba detectando miembros estáticos así como miembros no estáticos.

+0

Esto no requiere que 'U :: is_baz' sea estático. A 'struct A {bool is_baz; }; 'también funcionará. –

+0

@ JohannesSchaub-litb tienes razón. Parece que funciona ahora. – mfontanini

5

El problema en su código es que un objeto constexpr es implícitamente const, lo que significa que su prueba de mismo tipo debe ser:

std::is_same<const bool, decltype(U::is_baz)>::value 

Esto se especifica en la norma en §7.1.5 [DCL. constexpr]/9

Un especificador constexpr utilizado en una declaración de objeto declara el objeto como const. [...]

Cuestiones relacionadas