Reputation: 5342
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.
Upvotes: 7
Views: 266
Reputation: 4953
from the Wikipedia article about SFINAE - Substitution Failure is Not An Error:
[...] 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 [...]
In your code as posted, an ambiguity error occurs while instantiating the function template check
with parameter C
== 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 check
function template. The subsitution of the template parameter T of struct has_begin
is not relevant for the SFINAE rule, as that template has already been successfully instantiated.
Upvotes: 3