如何创建一个接受可变数量的int的C ++构造函数

时间:2016-05-20 16:03:20

标签: c++ variadic-functions

是否可以约束可变参数构造函数中的参数类型?

我希望能够表达

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吗?

4 个答案:

答案 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。