Zac*_*Saw 17 c++ gcc variadic-templates c++11
我想要一个简单接受无符号整数的可变参数模板.但是,我无法让以下工作.
struct Array
{
template <typename... Sizes> // this works
// template <unsigned... Sizes> -- this does not work (GCC 4.7.2)
Array(Sizes... sizes)
{
// This causes narrowing conversion warning if signed int is supplied.
unsigned args[] = { sizes... };
// ...snipped...
}
};
int main()
{
Array arr(1, 1);
}
Run Code Online (Sandbox Code Playgroud)
任何帮助赞赏.
编辑:如果你想知道,我正在尝试使用可变参数模板来复制以下内容.
struct Array
{
Array(unsigned size1) { ... }
Array(unsigned size1, unsigned size2) { ... }
Array(unsigned size1, unsigned size2, unsigned size3) { ... }
// ...
Array(unsigned size1, unsigned size2, ..., unsigned sizeN) { ... }
};
Run Code Online (Sandbox Code Playgroud)
我不确定你为什么要这样做.Clang告诉我错误是unknown type name 'Sizes'在构造函数的声明中.这是预期的,因为Sizes它不是一种类型(或者更确切地说,类型的模板包),它是一个值的模板包.
目前还不清楚你到底想要做什么.如果在模板参数中传递积分值,那么构造函数参数应该是什么?
更新:使用您的新代码,您只需要一个static_cast<unsigned>().
struct Array
{
template <typename... Sizes> // this works
Array(Sizes... sizes)
{
unsigned args[] = { static_cast<unsigned>(sizes)... };
// ...snipped...
}
};
Run Code Online (Sandbox Code Playgroud)
如果要接受必须全部为整数的动态参数,则需要普通的typename模板,但要检查所有类型是否(可转换为)无符号整数:
#include <type_traits>
struct Array
{
template <typename ...Args>
explicit Array(Args ...args,
typename std::enable_if<all_int<Args...>::value>::type * = nullptr);
// ...
};
Run Code Online (Sandbox Code Playgroud)
现在你只需要特质:
template <typename...> struct all_int;
template <> struct all_int<> : std::true_type { };
template <typename T, typename ...Rest> struct all_int<T, Rest...>
: std::integral_constant<bool,
std::is_convertible<T, unsigned int>::value && all_int<Rest>::value>
{ }
Run Code Online (Sandbox Code Playgroud)
如果您希望使类型严格,您也可以使用is_same而不是is_convertible.
另一种选择是完全放弃可变参数模板,并通过接受单个列表使列表可以初始化std::initializer_list<unsigned int>,这提供了更好的数字安全性(例如,禁止缩小转换).
查看初始化列表
你可以指定它像
struct Array
{
Array(std::initializer_list<unsigned> sizes)
{
for (auto i = sizes.begin(); i != sizes.end(); ++i)
...
}
}
Run Code Online (Sandbox Code Playgroud)
虽然,用法会更改为
Array arr = {1, 1};
Run Code Online (Sandbox Code Playgroud)