Reputation: 73
Similarily to this question is it possible to use SFINAE to determine if a type has a member function with a certain argument(s)? Without the argument list as answered in the other question and the std::void_t
example says it works fine. (I stood with the latter.) However, If I try to add a check for argument lust with extra std::decltype<>()
it fails with template parameters not deducible in partial specialization
. Is there any way to extend this method to check for certain argument types?
Example code:
#include <type_traits>
class A {
public :
void a(){}
void b(int val){}
};
class B {
public :
void b(float val){}
};
// --- Has function a() without arguments
template <typename T, typename = void> struct has_a : std::false_type
{
};
template <typename T> struct has_a<T, std::void_t<decltype(std::declval<T>().a())>> : std::true_type
{
};
template <typename T> constexpr bool has_a_v = has_a<T>::value;
// This is OK:
static_assert(true == has_a_v<A>);
static_assert(false == has_a_v<B>);
// --- Has function b() with one argument of one given type
template <typename T, typename U, typename = void> struct has_b : std::false_type
{
};
template <typename T ,typename U> struct has_b<T, std::void_t<decltype(std::declval<T>().b(std::declval<U>()))>> : std::true_type
{
};
template <typename T, typename U> constexpr bool has_b_v = has_b<T, U>::value;
// This fails with `template parameters not deducible in partial specialization`:
static_assert(true == has_b_v<A, int>);
static_assert(false == has_b_v<B, int>);
static_assert(false == has_b_v<A, float>);
static_assert(true == has_b_v<B, float>);
int main () { return 0;}
Upvotes: 1
Views: 265
Reputation: 6086
In your partial specialization, you forgot to add the U
parameter:
template <typename T, typename U>
struct has_b<
T,
U, // You forgot it
std::void_t<decltype(std::declval<T>().b(std::declval<U>()))>> : std::true_type
{
};
Upvotes: 2
Reputation: 55395
Yes. Example of a void_t
check for member function b
in class B
:
decltype( static_cast<void(B::*)(float)>(&B::b) )
This is if you want to check for exact signature. Your way is fine, too (once you fix it as commented under the question), but it actually checks if member function is callable with certain types of arguments (and ignores the return type).
Upvotes: 2