我想在模板类构造函数中接受最多多个参数(这个数字在模板参数中定义)。我不能使用 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>
. future 是否有支持此类功能的计划?甚至需要它吗?
最佳答案
你可以创建一个可变参数构造函数,然后断言它提供了正确数量的参数:
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
的参数传递给 Foo
的构造函数,您会在 static_assert
之前看到初始化 v
的错误。
对于更清晰的 static_assert
错误,您可以将顶级 Foo
委托(delegate)给私有(private)构造函数,这些构造函数采用额外的 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!");
}
关于c++ - 如何参数化构造函数的参数个数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30925553/