代码之家  ›  专栏  ›  技术社区  ›  Staffan Gustafsson

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

  •  21
  • Staffan Gustafsson  · 技术社区  · 10 年前

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

    我想表达

    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 回复  |  直到 10 年前
        1
  •  20
  •   granmirupa    10 年前

    你可以使用 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!
    
    }
    
        2
  •  16
  •   user2296177    10 年前

    由于您具有以下功能:

    template<int... values>
    struct Z
    {
        static int data[ sizeof...( values ) ];
    };
    
    template <int... values>
    int Z<values...>::data[ sizeof...( values ) ] = { values... };
    

    你可以使用 std::integer_sequence<> 将int传递给 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>{} );
    }
    
        3
  •  1
  •   Community Mohan Dere    9 年前

    您已经更新了您的问题,表明您只需要一个编译时 std::integer_sequence ,这很好。

    但为了将来的读者可能会来这里寻找答案,我也想回答您最初的问题“是否可以在变量构造函数中约束参数类型?”

    对一种方法(最好的方法?我不确定)是在额外的模板参数上使用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 .

        4
  •  -6
  •   Edward Strange    10 年前

    不,不能约束类型。你可以使用 static_assert 虽然应该是这样的:

    static_assert(std::is_same<int, Args>::value ..., "have to be ints.");
    

    尚未尝试在中使用扩展 static_assert(统计_断言) 尽管如此。您可能需要一个返回bool或其他值的constexpr。