简体   繁体   English

如何使特征接受参数包?

[英]How to make traits to accept a parameter pack?

I define some type traits like this:我定义了一些这样的类型特征:

template <typename T>
struct has_something
{
    static constexpr bool value = false;
};

template <> 
struct has_something<int>
{
    static constexpr bool value = true;
};

template <typename T>
constexpr bool has_something_v = has_something<T>::value;

And a function template which is has_something_v is a requirement for function parameter: function 模板has_something_v是 function 参数的要求:

template <typename T, typename = std::enable_if_t<has_something_v<T>>>
void some_function(const T temp)
{
}

When i call it with wrong type:当我用错误的类型调用它时:

struct wrong_type
{
};

void f ()
{
    some_function(wrong_type());
}

compiler give me a proper error message:编译器给我一个正确的错误信息:

/tmp/untitled/main.cpp:23: candidate template ignored: requirement 'has_something_v<wrong_type>' was not satisfied [with T = wrong_type]

but when i called with another template function:但是当我用另一个模板 function 调用时:

template <typename ...T, typename = std::enable_if_t<has_something_v<T...>>>
void some_function(const T... args)
{
    (some_function(args), ...);
}

void f ()
{
    some_function(1, 2, a());
}

compiler give me really bad and confusing error message because i don't have a parameter pack acceptable traits:编译器给了我非常糟糕和令人困惑的错误消息,因为我没有参数包可接受的特征:

Compiler error message编译器错误信息

And if i remove std::enable_if from last template function, everything work fine until i send a wrong_type type to function which result is in crashing program.如果我从最后一个模板 function 中删除std::enable_if ,一切正常,直到我将wrong_type类型发送到 function 导致程序崩溃。

For parameter pack, i wrote this:对于参数包,我写了这个:

template <typename ...T>
struct has_something
{
    static bool value;

    static constexpr bool c(T... args)
    {
        value = (args && ...);
        return value;
    }
};

template <>
struct has_something<int>
{
    static constexpr bool value = true;
};

template <typename ...T>
const bool has_something_v = has_something<T...>::value;

But it still fail.但它仍然失败。

How could i write a acceptable parameter pack type traits?我如何编写可接受的参数包类型特征?

If you want to make the trait accept a parameter pack and it's value be true only when the parameter pack has a single type and that type is int you need to change only little on your code:如果你想让 trait 接受一个参数包,并且只有当参数包具有单一类型并且该类型是int时它的值才为true ,你只需要对代码进行少量更改:

#include <iostream>
#include <type_traits>

template <typename...T>
struct has_something : std::false_type {};

template <> 
struct has_something<int> : std::true_type {};

template <typename... T>
constexpr bool has_something_v = has_something<T...>::value;

int main() {
    std::cout << has_something_v<int>;
    std::cout << has_something_v<double>;    
    std::cout << has_something_v<int,double>;
}

Using std::true_type and std::false_type makes traits a bit shorter to write.使用std::true_typestd::false_type会使特征写起来更短一些。 I only had to make the trait accept a parameter pack, the specialization can stay the same.我只需要让 trait 接受一个参数包,专业化就可以保持不变。

Last but not least you should pick a better name.最后但同样重要的是,您应该选择一个更好的名称。 For example is_one_int would be much better than something .例如is_one_int会比something好得多。

PS: SFINAE can be used to create compiler errors, but often a simple static_assert is the better choice to get a clean message: PS:SFINAE 可用于创建编译器错误,但通常简单的static_assert是获得干净消息的更好选择:

template <typename...T>
void foo(T...args) {
    static_assert( is_one_int_v<T...>, " put nice message here");
}

SFINAE is the tool of choice when you want to disambiguate different overloads, but if a function should simply fail without alternative then a static_assert is simpler.当您想消除不同的重载时,SFINAE 是首选工具,但如果 function 应该在没有替代方案的情况下简单地失败,那么static_assert会更简单。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM