2014-11-15 14 views
7

Próbuję przełączać się między jawnym i niejawnym konstruktorem konwersji przez enable_if.SFINAE enable_if jawny konstruktor

Moje kodu aktualnie wygląda

#include <type_traits> 
#include <cstdint> 

enum class enabled {}; 

template <bool B, typename T = void> using enable_if_t = typename std::enable_if<B, T>::type; 
template <bool B, typename T = void> using disable_if_t = typename std::enable_if<!B, T>::type; 

template <std::intmax_t A> struct SStruct 
{ 
    static constexpr std::intmax_t a = A; 
}; 

template <typename T> struct SCheckEnable : std::integral_constant<bool, T::a == 0> 
{ 
}; 

template <typename U, typename T> class CClass 
{ 
    public: 
     template <typename T2, enable_if_t<SCheckEnable<U>::value, enabled>...> constexpr CClass(T2 v) : val(v) {}; 
     template <typename T2, disable_if_t<SCheckEnable<U>::value, enabled>...> explicit constexpr CClass(T2 v) : val(v) {}; 

    private: 
     T val; 
}; 

int main() 
{ 
    CClass<SStruct<0>, double> a = 1;        // should use implicit constructor 
    CClass<SStruct<1>, double> b = CClass<SStruct<1>, double>(1); // should use explicit constructor 
} 

true w enable_if S jest zależna od parametru szablonu U

Gdy próbuję skompilować ten minimalny przykład z g++ 4.9.1 i --std=c++11 włączeniu pojawia się następujący błędy

sfinae.cpp: In substitution of ‘template<bool B, class T> using disable_if_t = typename std::enable_if<(! B), T>::type [with bool B = true; T = enabled]’: 
sfinae.cpp:13:52: required from here 
sfinae.cpp:7:95: error: no type named ‘type’ in ‘struct std::enable_if<false, enabled>’ 
template <bool B, typename T = void> using disable_if_t = typename std::enable_if<!B, T>::type; 
                          ^
sfinae.cpp:19:68: error: prototype for ‘constexpr CClass<U, T>::CClass(T2)’ does not match any in class ‘CClass<U, T>’ 
template <typename U, typename T> template <typename T2> constexpr CClass<U, T>::CClass(T2 v) : val(v) 
                    ^
sfinae.cpp:13:77: error: candidates are: template<class U, class T> template<class T2, int ...<anonymous> > constexpr CClass<U, T>::CClass(T2) 
    template <typename T2, disable_if_t<true, enabled>...> explicit constexpr CClass(T2 v); 
                      ^
sfinae.cpp:12:67: error:     template<class U, class T> template<class T2, enabled ...<anonymous> > constexpr CClass<U, T>::CClass(T2) 
    template <typename T2, enable_if_t<true, enabled>...> constexpr CClass(T2 v); 
                   ^

Każdy pomysł wybrać pomiędzy jawną i niejawną konstrukcją opartą na parametrze U?

+0

Mogę uzyskać [to działa dobrze] (http://coliru.stacked-crooked.com/a/f37eef8d7c290602). Nie wiem, jakie są różnice między Twoim kodem a moim. – Rapptz

+0

Czy przyczyną może być 'constexpr'? – Uroc327

+0

Nie. Nie powinno to mieć żadnego wpływu na SFINAE. Może mieć to związek z definiowaniem go poza klasą i sposobem, w jaki to robisz, ale nie jestem do końca przekonany. – Rapptz

Odpowiedz

3

Zastosowanie

template <class...> struct null_v : std::integral_constant<int, 0> {}; 

i definiują konstruktorzy jak

template <typename T2, 
      long = null_v<enable_if_t<SCheckEnable<U>::value, T2>>::value> 
constexpr CClass(T2 v) : val(v) {}; 

template <typename T2, 
      int = null_v<disable_if_t<SCheckEnable<U>::value, T2>>::value> 
explicit constexpr CClass(T2 v) : val(v) {}; 

Making argument zależne i faktycznie instancja. Demo.

[temp.deduct]/8:

Jeśli substytucja powoduje nieprawidłową ekspresją, typu lub typu odliczenie nie. Nieprawidłowy typ lub wyrażenie to taki, który byłby nieprawidłowo sformułowany, gdyby został zapisany pod przy użyciu podstawionych argumentów.

W twoim przypadku błąd występuje poza jakimkolwiek zamiennikiem, więc nie powoduje błędu odliczenia, ale powoduje, że twój kod jest źle sformułowany.

+0

Kompiluje i działa tak, jak powinien ... Gdzie dokładnie leży różnica między moją próbą a rozwiązaniem? – Uroc327

+1

Jeśli zrozumiałem komentarz 0x499602D2 poprawnie, enable_if musi "przetworzyć" coś z 'T2', ponieważ jest to parametr szablonu dla określonej funkcji, aby włączyć lub wyłączyć. Czy to rozumiem? :) – Uroc327

+0

@ Uroc327 Edytowano odpowiedź. – Columbo