我想在模板类构造函数中接受多个参数(此数字在模板参数中定义)。我不能使用initializer_list
,因为据我所知,我无法在编译时断言它的大小。
我的第一次尝试是使用std :: array作为参数:
template<size_t s>
class foo {
int v[s];
public:
foo(std::array<int, s>) {/*...*/}
};
然而,这迫使我像这样初始化(即使构造函数不是explicit
):
foo<4> a{{1,2,3,4}} // Two brackets.
我认为可能有一些模板魔术(可变参数模板?),但我甚至无法弄清楚在构造函数中使用的正确语法。我不能递归地调用构造函数...可以吗?
我试着寻找std::array
的构造函数的定义(因为它不允许比数组大小更多的参数,只是我想要的),但我能找到的只是它有隐式构造函数。这是默认的构造函数吗?如果是这样,怎么做
std::array<int, 3> a = {1,2,3}
工作?
可选奖励:为什么标准没有定义std::initializer_list
的固定尺寸替代?像std::static_initializer_list<T, N>
这样的东西。是否有计划在未来支持此类功能?它甚至需要吗?
答案 0 :(得分:10)
您可以创建一个可变参数构造函数,并断言它提供了正确数量的参数:
template <size_t SZ>
struct Foo {
template <typename... Args>
Foo(Args... args) {
static_assert(sizeof...(Args) <= SZ, "Invalid number of arguments");
// ... stuff ...
}
};
那样:
Foo<3> f; // OK
Foo<3> f(1, 2, 3); // OK
Foo<3> f(1, 2, 3, 4, 5); // error
作为初始化数组的示例,可能如下所示:
template <size_t SZ>
struct Foo {
template <typename... Args>
Foo(Args... args)
: v{{args...}}
{
static_assert(sizeof...(Args) <= SZ, "Invalid number of arguments");
}
std::array<int, SZ> v;
};
正如您所期望的那样正确构建v
,但如果您尝试将超过SZ
args传递给Foo
的构造函数,那么您可以d在v
之前看到有关初始化static_assert
的错误。
为了更清楚static_assert
错误,您可以将顶级Foo
委托给私有构造函数,这些构造函数对于它们是否为有效构造函数需要额外的integral_constant
参数:
template <typename... Args>
Foo(Args... args)
: Foo(std::integral_constant<bool, sizeof...(Args) <= SZ>{},
args...)
{ }
private:
template <typename... Args>
Foo(std::true_type, Args... args)
: v{{args...}}
{ }
template <typename False, typename... Args>
Foo(False, Args... )
{
// False is only ever std::false_type
static_assert(False::value, "Invalid number of arguments!");
}