【问题标题】:Templated check for the existence of a class member function with argument list?模板化检查是否存在带有参数列表的类成员函数?
【发布时间】:2020-06-24 11:55:52
【问题描述】:

this question 类似,是否可以使用 SFINAE 来确定类型是否具有带有特定参数的成员函数?如果没有其他问题中回答的参数列表,std::void_t example 表示它工作正常。 (我支持后者。)但是,如果我尝试使用额外的 std::decltype<>() 添加对参数 lust 的检查,它会以 template parameters not deducible in partial specialization 失败。有没有办法扩展这个方法来检查某些参数类型?

示例代码:


#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;}

【问题讨论】:

  • 你有一个错字。 std::declval&lt;T&gt;().b(std::declval(U)) 应该是 std::declval&lt;T&gt;().b( std::declval&lt;U&gt;())
  • @Caiwan 你还有一个错字——has_b 的部分特化需要三个模板参数:&lt;T, U, std::void_t...&gt;

标签: c++ templates c++17 sfinae


【解决方案1】:

是的。 void_t 在类B 中检查成员函数b 的示例:

decltype( static_cast<void(B::*)(float)>(&B::b) )

这是如果你想检查 exact 签名。你的方法也很好(一旦你按照问题下的评论修复它),但它实际上检查成员函数是否 callable 具有某些类型的参数(并忽略返回类型)。

【讨论】:

    【解决方案2】:

    在您的部分专业化中,您忘记添加 U 参数:

    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
    {
    };
    

    【讨论】:

      猜你喜欢
      • 2021-09-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-23
      • 1970-01-01
      • 2015-01-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多