I've written this code to check if a class type have begin
function.
struct foo //a simple type to check
{
int begin(){ return 0;}
};
struct Fallback
{
int begin(){ return 0;}
};
template<typename T>
struct HasfuncBegin : T,Fallback
{
typedef char one;
typedef int two;
template<typename X>
static one check(int (X::*)() = &HasfuncBegin<T>::begin);
template<typename X>
static two check(...);
enum :bool {yes = sizeof(check<T>())==1, no= !yes};
};
int main()
{
std::cout<< HasfuncBegin<foo>::yes;
return 0;
}
Which produces error :
error: call of overloaded 'check()' is ambiguous
enum {yes = sizeof(check<T>())==1, no= !yes};
^
C:\XXX\main.cpp:24:16: note: candidate: static HasfuncBegin<T>::one HasfuncBegin<T>::check(int (X::*)()) [with X = foo; T = foo; HasfuncBegin<T>::one = char]
static one check(int (X::*)() = &HasfuncBegin<T>::begin);
^
C:\XXX\main.cpp:26:16: note: candidate: static HasfuncBegin<T>::two HasfuncBegin<T>::check(...) [with X = foo; T = foo; HasfuncBegin<T>::two = int]
static two check(...);
^
Can anyone please explain why call is ambiguous (even though first check function with signature one check(int (X::*)() = &HasfuncBegin<T>::begin);
has default argument to be used) and also how to make my code work?
Edit:
So here is final working code :
struct foo
{
int begin(){ return 0;}
};
struct Fallback
{
int begin(){ return 0;}
};
template<typename T, T ptr> struct dummy{};
template<typename T>
struct HasfuncBegin : T,Fallback
{
typedef char one;
typedef int two;
template<typename X>
static one check(dummy<int (X::*)(),&HasfuncBegin<X>::begin>*);
// even this won't work, so replace above statement with below commented one
// static one check(dummy<decltype(&HasfuncBegin<X>::begin),&HasfuncBegin<X>::begin>*);
template<typename X>
static two check(...);
enum {yes = sizeof(check<T>(0))==1, no= !yes};
};
The reason for the ambiguity is that both (templated) overloads of check()
are valid matches for check<T>()
. You may think one is more valid than the other but the rules of the language is that they are both equally valid.
A variable argument function (...
) is a match for zero or more arguments (i.e. check<T>()
). A function with a single argument that has a default value can match check<T>()
.
Hence the message about ambiguity.
You haven't actually described what you are trying to achieve with this code (particularly the initialisation of the enum
), but are somehow expecting we will work out what you are trying to do. The obvious way to get it to compile would be to remove one of the overloads.
But, unless you describe what you are really trying to achieve, nobody can advise you. Reading sites like this does not grant people mindreading powers.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With