[英]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:编译器给了我非常糟糕和令人困惑的错误消息,因为我没有参数包可接受的特征:
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_type
和std::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.