I\'m asking for a template trick to detect if a class has a specific member function of a given signature.
The problem is similar to the one cited here http://www.go
You appear to want the detector idiom. The above answers are variations on this that work with C++11 or C++14.
The std::experimental
library has features which do essentially this. Reworking an example from above, it might be:
#include
// serialized_method_t is a detector type for T.serialize(int) const
template
using serialized_method_t = decltype(std::declval.serialize(std::declval()));
// has_serialize_t is std::true_type when T.serialize(int) exists,
// and false otherwise.
template
using has_serialize_t = std::experimental::is_detected_t;
If you can't use std::experimental, a rudimentary version can be made like this:
template
using void_t = void;
template class Trait, class AlwaysVoid, class... Args>
struct detector : std::false_type {};
template class Trait, class... Args>
struct detector>, Args...> : std::true_type {};
// serialized_method_t is a detector type for T.serialize(int) const
template
using serialized_method_t = decltype(std::declval.serialize(std::declval()));
// has_serialize_t is std::true_type when T.serialize(int) exists,
// and false otherwise.
template
using has_serialize_t = typename detector::type;
Since has_serialize_t is really either std::true_type or std::false_type, it can be used via any of the common SFINAE idioms:
template
std::enable_if_t::value, std::string>
SerializeToString(const T& t) {
}
Or by using dispatch with overload resolution:
template
std::string SerializeImpl(std::true_type, const T& t) {
// call serialize here.
}
template
std::string SerializeImpl(std::false_type, const T& t) {
// do something else here.
}
template
std::string Serialize(const T& t) {
return SerializeImpl(has_serialize_t{}, t);
}