template<typename U> struct CheckSignature {
enum {SizeTrue = 1, SizeFalse = 2};
typedef char ReturnTrue[SizeTrue];
typedef char ReturnFalse[SizeFalse];
typedef typename U::iterator (U::*InsertSig)(typename U::iterator, typename const U::value_type &);
static ReturnTrue &CheckInsert(InsertSig);
static ReturnFalse &CheckInsert(...);
static const bool value = (sizeof(CheckInsert(&U::insert)) == sizeof(ReturnTrue));
};
int main() {
CheckSignature<std::string >::value; //compile error
CheckSignature<std::vector<int> >::value; // OK
return 0;
}
This code generates a compile error for the string class saying that none of the 2 overloads could convert all argument types. However, for vector it compiles fine. Shouldn’t overload resolution choose CheckInsert(…) whenever the parameter isn’t of type InsertSig?
Try this instead:
The reason why it doesn’t work is because, in your version, taking the address of the insert function will fail at the call site, not at the substitution (which is not an error). The above will make sure that if the type U (templated to T) cannot be used to obtain a member function pointer to insert which is convertable to the given signature, it will fail to substitute for the dummy parameter, and thus, revert to the ellipsis version.