Lets say I have
struct foo {
void ham() {}
void ham() const {}
};
struct bar {
void ham() {}
};
Assuming I have a templated function, can I tell whether given type has a const overload for ham
?
With
#define DEFINE_HAS_SIGNATURE(traitsName, funcName, signature) \
template <typename U> \
class traitsName \
{ \
private: \
template<typename T, T> struct helper; \
template<typename T> \
static std::uint8_t check(helper<signature, &funcName>*); \
template<typename T> static std::uint16_t check(...); \
public: \
static \
constexpr bool value = sizeof(check<U>(0)) == sizeof(std::uint8_t); \
}
DEFINE_HAS_SIGNATURE(has_ham_const, T::ham, void (T::*)() const);
And then
static_assert(has_ham_const<foo>::value, "unexpected");
static_assert(!has_ham_const<bar>::value, "unexpected");
Demo
SFINAE over and over again. Here is another option which is unspecified about the return types but lets you specify the arguments.
(For comparison: the approach by @Jarod42 checks the exact signature, return type + arguments, the other void_t
expression sfinae stuff up to now checks only whether ham()
can be called.)
Plus, it works with the current MSVC 2015 Update 1 version (unlike the usual void_t
stuff).
template<typename V, typename ... Args>
struct is_callable_impl
{
template<typename C> static constexpr auto test(int) -> decltype(std::declval<C>().ham(std::declval<Args>() ...), bool{}) { return true; }
template<typename> static constexpr auto test(...) { return false; }
static constexpr bool value = test<V>(int{});
using type = std::integral_constant<bool, value>;
};
template<typename ... Args>
using is_callable = typename is_callable_impl<Args...>::type;
Use it as
struct foo
{
void ham() {}
void ham() const {}
int ham(int) const {}
};
int main()
{
std::cout
<<is_callable<foo>::value //true
<<is_callable<const foo>::value //true
<<is_callable<const foo, int>::value //true
<<is_callable<const foo, double>::value //also true, double is converted to int
<<is_callable<const foo, std::string>::value //false, can't call foo::ham(std::string) const
<<std::endl;
}
Demo on Coliru
For the "newest" sfinae stuff, however, I suggest you have a look at boost.hana.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With