Шаблоны создания путаницы - PullRequest
7 голосов
/ 15 декабря 2011

Это мой код, чтобы проверить, имеет ли класс функцию-член begin или нет:

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};
};

Если я изменю второй аргумент cht в check(cht< Iter (fallBack::*)() const, &C::begin>*); на &checker::begin, Это не меняет семантику кода, поскольку второй аргумент шаблона cht всегда равен checker из-за этого enum {no = (sizeof(check<checker>(0))==sizeof(char))

но изменение кода приводит к ошибка сейчас, которые:

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

Я хочу знать, в чем причина такого поведения.

1 Ответ

3 голосов
/ 15 декабря 2011

из статьи в Википедии о SFINAE - ошибка замещения не является ошибкой:

[...] при создании набора кандидатов для разрешения перегрузки некоторые (или все) кандидаты из этого набора могутбыть результатом замены выведенных аргументов шаблона для параметров шаблона.Если во время подстановки возникает ошибка, компилятор удаляет потенциальную перегрузку из набора кандидатов, а не останавливается с ошибкой компиляции [...]

В опубликованном вами коде возникает ошибка неоднозначности при создании экземплярашаблон функции check с параметром C == typename has_begin<T>::checker, и эта подстановка приводит к ошибке, поэтому создание экземпляра просто удаляется из набора перегрузки.

Если вы измените свой код, аналогичноНеоднозначная ошибка возникает с &checker::begin.Однако на этот раз это не результат замены параметра шаблона C на шаблон функции check.Подстановка параметра шаблона T struct has_begin не относится к правилу SFINAE, так как этот шаблон уже успешно создан.

...