2011-12-15 12 views
7

To jest mój kod, aby sprawdzić, czy klasa ma funkcję składową begin czy nie:Szablony instancji zamieszanie

template<typename T> struct has_begin 
{ 
    struct dummy {typedef void const_iterator;}; 
    typedef typename std::conditional< has_iterator<T>::yes, T, dummy>::type TType; 
    typedef typename TType::const_iterator Iter; 
    struct fallBack{ Iter begin() const ; Iter end() const;}; 
    struct checker : T, fallBack {}; 
    template <typename B, B> struct cht; 
    template<typename C> static char check(cht< Iter (fallBack::*)() const, &C::begin>*); // problem is here 
    template<typename C> static char (&check(...))[2]; 
public: 
    enum {no = (sizeof(check<checker>(0))==sizeof(char)), 
    yes=!no}; 
}; 

Jeśli zmienię drugi argument cht w check(cht< Iter (fallBack::*)() const, &C::begin>*); do &checker::begin, nie zmienia semantycznego kodu ponieważ drugi szablon argumentem cht „s jest zawsze checker powodu tej enum {no = (sizeof(check<checker>(0))==sizeof(char))

ale zmiany kodu powoduje error teraz którymi są:

prog.cpp: In instantiation of 'has_begin<std::vector<int> >': 
prog.cpp:31:51: instantiated from here 
prog.cpp:23:38: error: reference to 'has_begin<std::vector<int> >::checker::begin' is ambiguous 

Chcę wiedzieć, jaka jest przyczyna tego zachowania.

+0

Twoja struktura jest bardzo złożona. Co ma robić? Wygląda jak sprawdzanie, czy klasa T ma funkcję składową o nazwie start –

+0

@VJovic Masz rację, edytowałem pierwszą linię Q :) –

+0

Jaki błąd otrzymasz po wprowadzeniu zmiany? –

Odpowiedz

3

z artykułu z Wikipedii o SFINAE - Brak Zmiana to nie błąd:

[...] when creating a candidate set for overload resolution, some (or all) candidates of that set may be the result of substituting deduced template arguments for the template parameters. If an error occurs during substitution, the compiler removes the potential overload from the candidate set instead of stopping with a compilation error [...]

W kodzie, jak pisał, błąd występuje podczas dwuznaczność instancji szablonu funkcji check z parametrem C == typename has_begin<T>::checker i że podstawienie prowadzi do błędu, więc instancja jest po prostu usuwana z zestawu przeciążeniowego.

Jeśli zmienisz kod, pojawi się podobny błąd w postaci ambiguaty z &checker::begin. Tym razem nie jest to wynikiem zastąpienia parametru szablonu C dla szablonu funkcji check. Podpisanie parametru szablonu T struct has_begin nie jest istotne dla reguły SFINAE, ponieważ ten szablon został już pomyślnie utworzony.

+0

Twój pierwszy akapit nie ma dla mnie sensu. wyjaśnić powód bardziej wyraźnie? –

+0

@FreakEnum edytowane odpowiedź, mam nadzieję, że pomaga – wolfgang