Created
October 29, 2015 12:09
-
-
Save Jiwan/2573fc47e4fa5025306b to your computer and use it in GitHub Desktop.
C++98 SFINAE usage for serialization
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
struct A {}; | |
std::string to_string(const A&) | |
{ | |
return "I am a A!"; | |
} | |
// Type B with a serialize method. | |
struct B | |
{ | |
std::string serialize() const | |
{ | |
return "I am a B!"; | |
} | |
}; | |
// Type C with a "wrong" serialize member (not a method) and a to_string overload. | |
struct C | |
{ | |
std::string serialize; | |
}; | |
std::string to_string(const C&) | |
{ | |
return "I am a C!"; | |
} | |
struct D : A | |
{ | |
std::string serialize() const | |
{ | |
return "I am a D!"; | |
} | |
}; | |
struct E | |
{ | |
struct Functor | |
{ | |
std::string operator()(){ | |
return "I am a E!"; | |
} | |
}; | |
Functor serialize; | |
}; | |
// Structures are good as they expose everything in public! | |
template <class T> struct hasSerialize | |
{ | |
// For the compile time comparison. | |
typedef char yes[1]; | |
typedef yes no[2]; | |
// This helper struct permits us to check two properties of a template argument. | |
template <typename U, U u> struct reallyHas; | |
// Two overloads for yes: one if for the signature of a normal method, one is for the signature of a const method. | |
template <typename C> static yes& test(reallyHas<std::string (C::*)(), &C::serialize>* /*unused*/) { } | |
template <typename C> static yes& test(reallyHas<std::string (C::*)() const, &C::serialize>* /*unused*/) { } | |
// The famous C++ sink-hole. | |
// Note that sink-hole must be templated too as we are testing test<T>(0). | |
template <typename> static no& test(...) { /* dark matter */ } | |
// The constant used as a return value for the test. | |
enum { value = sizeof(test<T>(0)) == sizeof(yes) }; | |
}; | |
template <class T> bool testHasSerialize(const T& /*t*/) { return hasSerialize<T>::value; } | |
template<bool B, class T = void> | |
struct enable_if {}; | |
template<class T> | |
struct enable_if<true, T> { typedef T type; }; | |
template <class T> typename enable_if<hasSerialize<T>::value, std::string>::type serialize(const T& obj) | |
{ | |
return obj.serialize(); | |
} | |
template <class T> typename enable_if<!hasSerialize<T>::value, std::string>::type serialize(const T& obj) | |
{ | |
return to_string(obj); | |
} | |
int main() { | |
A a; | |
B b; | |
C c; | |
std::cout << serialize(a) << std::endl; | |
std::cout << serialize(b) << std::endl; | |
std::cout << serialize(c) << std::endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment