如何创建一个接受可变数量的 int 的 C++ 构造函数
How can I create a C++ constructor that accepts a variable number of int's
是否可以在可变参数构造函数中限制参数类型?
我想表达
X x1(1,3,4);
X x2(3,4,5);
// syntax error: identifier 'Args'
class X {
template<int ... Args> X(Args...)
{
}
};
// this works but allows other types than int
class Y {
template<typename ... Args> Y(Args...)
{
}
};
编辑以阐明意图:
我想要实现的是将传递给构造函数的数据(编译时已知的常量)存储到静态数组中。
所以还有一些其他的
template<int ...values>
struct Z
{
static int data[sizeof...(values)];
};
template<int ... values>
int Z<values...>::data[sizeof...(values)] = {values...};
在 X 的构造函数中,我想像这样使用 Z:
class X {
template<int ... Args> X(Args...)
{
Z<Args...>::data // do stuff with data
}
};
这可能吗,我必须使用integer_sequence吗?
不,您不能限制类型。不过,您可以使用 static_assert
。会是这样的:
static_assert(std::is_same<int, Args>::value ..., "have to be ints.");
虽然没有尝试在 static_assert
中使用扩展。您可能需要一个 returns bool 或其他东西的 constexpr。
因为你有:
template<int... values>
struct Z
{
static int data[ sizeof...( values ) ];
};
template <int... values>
int Z<values...>::data[ sizeof...( values ) ] = { values... };
您可以使用 std::integer_sequence<>
将整数传递给 Z<>
:
struct X
{
template <int... values>
X( std::integer_sequence<int, values...> )
{
for ( int i{ 0 }; i < sizeof...( values ); ++i )
Z<values...>::data[ i ]; // do stuff with data
}
};
你可以让自己成为一个助手类型,以便于调用ctor:
template <int... values>
using int_sequence = std::integer_sequence<int, values...>;
然后你可以像这样实例化你的class:
int main()
{
X x( int_sequence<1, 3, 5>{} );
}
您可以使用 std::initializer_list
:
#include <iostream>
#include <initializer_list>
void myFunc(std::initializer_list<int> args)
{
for (int i: args) std::cout << i << '\n';
}
int main(){
myFunc({2,3,2});
// myFunc({2,"aaa",2}); error!
}
您已更新您的问题以表明您所需要的只是一个编译时std::integer_sequence
,这很好。
但为了未来可能会来这里寻找答案的读者,我也想回答你原来的问题 "Is it possible to constrain the type of arguments in a variadic constructor?"
是的。一种方法(最好的方法?我不确定)是在额外的模板参数上使用 SFINAE,如下所示:
struct X {
template<
class... TT,
class E = std::enable_if_t<(std::is_same_v<TT, int> && ...)>
>
X(TT... tt) {
// do stuff with the ints "tt..."
}
};
&& ...
是折叠表达式,C++17 中的新功能。如果您的编译器不支持折叠表达式,只需将其替换为手动 all_of
.
是否可以在可变参数构造函数中限制参数类型?
我想表达
X x1(1,3,4);
X x2(3,4,5);
// syntax error: identifier 'Args'
class X {
template<int ... Args> X(Args...)
{
}
};
// this works but allows other types than int
class Y {
template<typename ... Args> Y(Args...)
{
}
};
编辑以阐明意图:
我想要实现的是将传递给构造函数的数据(编译时已知的常量)存储到静态数组中。
所以还有一些其他的
template<int ...values>
struct Z
{
static int data[sizeof...(values)];
};
template<int ... values>
int Z<values...>::data[sizeof...(values)] = {values...};
在 X 的构造函数中,我想像这样使用 Z:
class X {
template<int ... Args> X(Args...)
{
Z<Args...>::data // do stuff with data
}
};
这可能吗,我必须使用integer_sequence吗?
不,您不能限制类型。不过,您可以使用 static_assert
。会是这样的:
static_assert(std::is_same<int, Args>::value ..., "have to be ints.");
虽然没有尝试在 static_assert
中使用扩展。您可能需要一个 returns bool 或其他东西的 constexpr。
因为你有:
template<int... values>
struct Z
{
static int data[ sizeof...( values ) ];
};
template <int... values>
int Z<values...>::data[ sizeof...( values ) ] = { values... };
您可以使用 std::integer_sequence<>
将整数传递给 Z<>
:
struct X
{
template <int... values>
X( std::integer_sequence<int, values...> )
{
for ( int i{ 0 }; i < sizeof...( values ); ++i )
Z<values...>::data[ i ]; // do stuff with data
}
};
你可以让自己成为一个助手类型,以便于调用ctor:
template <int... values>
using int_sequence = std::integer_sequence<int, values...>;
然后你可以像这样实例化你的class:
int main()
{
X x( int_sequence<1, 3, 5>{} );
}
您可以使用 std::initializer_list
:
#include <iostream>
#include <initializer_list>
void myFunc(std::initializer_list<int> args)
{
for (int i: args) std::cout << i << '\n';
}
int main(){
myFunc({2,3,2});
// myFunc({2,"aaa",2}); error!
}
您已更新您的问题以表明您所需要的只是一个编译时std::integer_sequence
,这很好。
但为了未来可能会来这里寻找答案的读者,我也想回答你原来的问题 "Is it possible to constrain the type of arguments in a variadic constructor?"
是的。一种方法(最好的方法?我不确定)是在额外的模板参数上使用 SFINAE,如下所示:
struct X {
template<
class... TT,
class E = std::enable_if_t<(std::is_same_v<TT, int> && ...)>
>
X(TT... tt) {
// do stuff with the ints "tt..."
}
};
&& ...
是折叠表达式,C++17 中的新功能。如果您的编译器不支持折叠表达式,只需将其替换为手动 all_of
.