I'm attempting to use SFINAE to detect if a type passed as a template argument T has an T::operator()(P const&) where P is also a template argument. I modeled my solution after this example of the Member Detector Idiom Unfortunately, I could not get this working for an operator(), even though I could get it to function for a normal method.
Here's some sample code that demonstrates the problem I'm facing:
#include <iostream>
#include <iomanip>
#include <utility>
#include <type_traits>
using namespace std;
struct has
{
void operator()(int const&);
};
struct hasNot1
{
void operator()(int);
};
struct hasNot2
{
void operator()();
};
struct hasNot3
{
void operator()(float);
};
struct hasNot4
{
};
template<typename T, typename EDT>
struct is_callable_oper
{
private:
typedef char(&yes)[1];
typedef char(&no)[2];
template <typename U, void (U::*)(EDT const &)> struct
Check;
template<typename>
static yes test(...);
template <typename U>
static no
test(Check<U, &U::operator()>*);
public:
static constexpr bool value = sizeof(test<T>(0))
== sizeof(yes);
};
int main() {
cout << boolalpha << is_callable_oper<has, int&>::value << " "
<< is_callable_oper<has, int>::value << " "
<< is_callable_oper<hasNot1, int&>::value << " "
<< is_callable_oper<hasNot2, int&>::value << " "
<< is_callable_oper<hasNot3, int&>::value << " "
<< is_callable_oper<hasNot4, int&>::value << endl;
return 0;
}
Running it on ideone (https://ideone.com/tE49xR) produces:
true false true true true true
I expected:
true false false false false false
Work Done:
Read this Stackoverflow question. I've also followed related links.
Looked up std::declval, decltype. I've also studied a bit on how the non-type template parameter results in an ambiguity. I've been using http://en.cppreference.com/ primarily.
Read some other related questions and links.
Note: I'm working on gcc 4.6.3 with C++ 0x.
End Goal: Detect all callables function pointers included with this signature.
Related Clarifications: I'm still confused about some concepts, and I would be grateful if you could answer these. Of course, if they belong in a separate question, please do let me know.
Can we trigger the ambiguity for SFINAE by using declval rather than a Check template for this case?
What is the function type for an overloaded operator? For example, would the overloaded operator in this case have the following type:
void (operator())(EDT const&)
?As CV Qualifiers are discarded during this check, what is the best way to check for the const-ness of the argument I'm passing.\
I haven't been able to figure out a way to use Boost to do this. I'm also stuck using an older Boost version 1.43 (Will check and update the exact), I believe. If there is no reason to roll my own check, that may be for the best.
I'm still very much a beginner in this area, and I sincerely apologize if this is too basic. I would appreciate it if you can point me to additional resources that you think I should be looking at as well. In the meantime, I'll keep searching online and trying solutions.
EDIT 1
After discussing the problem with @Nir Friedman, I have come to appreciate that breaking implicit conversion rules and achieving an exact match is not what I want. So long as the passed type can be converted, it should be fine. I would appreciate a pointer on how to achieve this.
EDIT 2
I'm marking this question as closed because @Sam Varshavchik answered the exact question I asked. If anyone is interested in the question posed in EDIT 1, I'll either ask it as a separate question, or post my solution here for reference.