是否可以约束可变参数构造函数中的参数类型?
我希望能够表达
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吗?
答案 0 :(得分:16)
您可以使用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!
}
答案 1 :(得分:15)
由于您有以下内容:
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...>;
然后你可以这样实例化你的类:
int main()
{
X x( int_sequence<1, 3, 5>{} );
}
答案 2 :(得分:1)
您已更新了问题,表明您所需要的只是编译时std::integer_sequence
,这很棒。
但是为了将来可能来这里寻找答案的读者,我也想回答你原来的问题&#34;是否有可能在可变参数构造函数中约束参数的类型? &#34;
是。一种方法(最好的方法?我不确定)是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..."
}
};
&& ...
是一个fold-expression,在C ++ 17中是新的。如果您的编译器不支持折叠表达式,只需用手动all_of
替换它。
答案 3 :(得分:-5)
不,你不能约束这种类型。您可以使用static_assert
。会是这样的:
static_assert(std::is_same<int, Args>::value ..., "have to be ints.");
尽管如此,还没有尝试在static_assert
中使用扩展。你可能需要一个返回bool或其他东西的constexpr。