【问题标题】:Create different template versions based on member presence根据成员存在创建不同的模板版本
【发布时间】:2021-11-11 21:44:13
【问题描述】:

我想要一个这样的模板函数:

template <typename T>
void ReadHelper(T vector_array[])
{
    // some code
}

T 是一些结构。但是这个结构有两个不同的版本:

struct type1 {
    float data;
}

struct type2 {
    float data;
    bool valid;
}

我希望ReadHelper 能够设置valid 标志。编写两个不同的 templated 函数以正确处理这两种类型的结构的好方法是什么?我当然可以为我的所有类型编写重载版本,但这很乏味。有没有 如何正确设置模板来做到这一点?或许是 SFINAE?

【问题讨论】:

  • 当函数只能采用 2 种类型并且您需要为它们定义函数时,这如何是模板函数?这只是函数重载。
  • @NicolBolas 我只举了两个例子。还有很多。它们仅属于 2 个类别

标签: c++ templates stl c++14 sfinae


【解决方案1】:

SFINAE 绝对是一个解决方案!我使用Templated check for the existence of a class member function? 作为参考。

下面是一个示例,说明您可以如何做到这一点。 has_valid 类型很重要;我用它来进行函数调度,但你也可以以其他方式使用它。在您的情况下,您只需调用 set_valid(vector_array[i]) 或您的读取助手中的任何内容。

// SFINAE check for if T has member valid
// note this doesn't check that the member is a bool
template<class T>
class has_valid
{
    template<class X>
    static std::true_type check(decltype(X::valid));

    // Use this version instead if you want to 
    // check if X::valid is explicitly a bool
    /*
    template<class X>
    static std::true_type check(std::enable_if_t<
                                     std::is_same_v<decltype(X::valid), bool>,
                                     bool
                                >);
    */

    template<class X>
    static std::false_type check(...);

  public:
    using type = decltype(check<T>(true));
    constexpr static auto value = type();
};

// Friendly helpers
template<class T>
using has_valid_t = typename has_valid<T>::type;

template<class T>
constexpr static auto has_valid_v = has_valid<T>::value;

// Function dispatcher; call set_valid, which will use has_valid_t to
// dispatch to one of the overloads of dispatch_set_valid, where you can
// either set or not set the value as appropriate
template<class T>
void dispatch_set_valid(T& t, std::false_type)
{
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}

template<class T>
void dispatch_set_valid(T& t, std::true_type)
{
    t.valid = true;
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}

template<class T>
void set_valid(T& t)
{
    dispatch_set_valid(t, has_valid_t<T>());
}

在编译器资源管理器中查看它的实际效果:https://godbolt.org/z/sqW17WYc6

【讨论】:

    猜你喜欢
    • 2020-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多