This is my code to check whether class has member function begin or not :
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};
};
If I change second argument of cht in check(cht< Iter (fallBack::*)() const, &C::begin>*); to
&checker::begin , This doesn’t changes the semantic of code since cht‘s second template argument is always checker due to this enum {no = (sizeof(check<checker>(0))==sizeof(char))
but code change results in error now which are :
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
I want to know what is the reason behind this behavior.
from the Wikipedia article about SFINAE – Substitution Failure is Not An Error:
In your code as posted, an ambiguity error occurs while instantiating the function template
checkwith parameterC==typename has_begin<T>::checker, and that substitution leads to the error, so the instantiation is simply removed from the overload set.If you change your code, a similar ambiguaty error occurs with
&checker::begin.This time, however, it is not the result of substituting the template parameter C for the
checkfunction template. The subsitution of the template parameter T ofstruct has_beginis not relevant for the SFINAE rule, as that template has already been successfully instantiated.