Why don't you use specialization like this:
struct P1 {int x; };
struct P2 {int X; };
template<class P>
bool Check_x(P p) { return true; }
template<>
bool Check_x<P2>(P2 p) { return false; }
Why don't you use specialization like this:
struct P1 {int x; };
struct P2 {int X; };
template<class P>
bool Check_x(P p) { return true; }
template<>
bool Check_x<P2>(P2 p) { return false; }
Why don't you just create template specializations of Check_x ?
template<> bool Check_x(P1 p) { return true; }
template<> bool Check_x(P2 p) { return false; }
Heck, when I think of it. If you only have two types, why do you even need templates for this?
The second answer (litb's) to this shows how to detect a member:
http://stackoverflow.com/questions/257288/possible-for-c-template-to-check-for-a-functions-existence
Try this:
template<class X, bool=&X::x> struct Check_x_t;
template<class P> bool Check_x(P p, Check_x_t<P>* = 0) { return true; }
template<class P> bool Check_x(P p, ...) { return false; }
struct P1 {int x; };
struct P2 {int X; };
void test()
{
P1 p1; P2 p2;
Check_x(p1); // returns true
Check_x(p2); // returns false
}
The following link explains why your first solution is failing on certain compilers:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2634.html
(it fails on Comeau as well as VC).
Are the functions (x, X, y, Y) from an abstract base class, or could they be refactored to be so? If so you can use the SUPERSUBCLASS() macro from Modern C++ Design, along with ideas from the answer to this question:
http://stackoverflow.com/questions/145814/compile-time-type-based-dispatch
Another way is this one, which relies on SFINAE for expressions too. If the name lookup results in ambiguity, the compiler will reject the template
template<typename T> struct HasX {
struct Fallback { int x; }; // introduce member name "x"
struct Derived : T, Fallback { };
template<typename C, C> struct ChT;
template<typename C> static char (&f(ChT<int Fallback::*, &C::x>*))[1];
template<typename C> static char (&f(...))[2];
static bool const value = sizeof(f<Derived>(0)) == 2;
};
struct A { int x; };
struct B { int X; };
int main() {
std::cout << HasX<A>::value << std::endl; // 1
std::cout << HasX<B>::value << std::endl; // 0
}
It's based on a brilliant idea of someone on usenet.
Boost.ConceptTraits provides between others some macros to define type traits, as for example BOOST_TT_EXT_DEFINE_HAS_MEMBER(name)
, which defines a type trait of the form:
has_member_##name<T>
This gives true if T has a member type named . Note, however, that this won't detect reference type members.
In you case it will be enough to add in a header file
BOOST_TT_EXT_DEFINE_HAS_MEMBER_TYPE(x)
and check as follows
BOOST_STATIC_ASSERT(has_member_x<P1>::value);
The technique used is the same as the one explained on some of the preceding answers.
Unfortunately this library is no more maintained. Now that C++0x will not includes concept, this library together with SFINAE is a perfect replacement to work with most of the concepts.