基于模板参数的模板类强制参数数

时间:2017-09-21 21:20:33

标签: c++ templates variadic-templates

我有一个可以基于单个尺寸参数进行模板化的类。我想有一个构造函数,它根据模板大小参数接受可变数量的std::array。所以,如果这个类被模板化为一个。它应该接受一个数组。如果模板化为2,它应该接受两个等。

这是我提出的,但显然它不起作用:

template<std::size_t V>
class Test
{
public:

    /* Constructors. */
    Test() {}

    template <std::array<int, 3> ...Args, typename = typename std::enable_if<V == sizeof...(Args), void>::type>
    Test(std::array<int, 3>&&... args) 
    {

    }

};


int main()
{
    auto t = Test<1>({ 1, 2, 3 });
    auto t2 = Test<2>(
        { 1, 2, 3 },
        { 4, 5, 6 }
    );
}

我收到的错误是:

error C2993: 'std::array<int,3>': illegal type for non-type template parameter 'Args'
note: see reference to class template instantiation 'Test<V>' being compiled
error C3543: 'std::array<int,3> &&': does not contain a parameter pack
error C2440: '<function-style-cast>': cannot convert from 'initializer list' to 'Test<1>'
note: No constructor could take the source type, or constructor overload resolution was ambiguous
error C2440: '<function-style-cast>': cannot convert from 'initializer list' to 'Test<2>'
note: No constructor could take the source type, or constructor overload resolution was ambiguous

感谢任何帮助。

2 个答案:

答案 0 :(得分:2)

有了继承,你可以这样做:

template <std::size_t, typename T> using alwaysT = T;

template <typename T, typename Seq> struct TestHelper;

template <typename T, std::size_t ... Is>
struct TestHelper<T, std::index_sequence<Is...>>
{
    TestHelper(alwaysT<Is, T>... arr) {}
};

template<std::size_t V>
class Test : TestHelper<const std::array<int, 3>&, std::make_index_sequence<V>>
{
public:
    using TestHelper<const std::array<int, 3>&, std::make_index_sequence<V>>::TestHelper;
    Test() = default;
};

Demo

答案 1 :(得分:1)

评论中的一些有效解决方案:

#include <type_traits>
#include <array>

template<typename... TArgs> struct
contains_only_array_of_3_int
{
    static constexpr bool const value{false};
};

template<typename TBack> struct
contains_only_array_of_3_int<TBack>
{
    static constexpr bool const value
    {
        ::std::is_same<::std::array<int, 3>, TBack>::value
    };
};

template<typename TFront, typename... TRest> struct
contains_only_array_of_3_int<TFront, TRest...>
{
    static constexpr bool const value
    {
        contains_only_array_of_3_int<TFront>::value
        &&
        contains_only_array_of_3_int<TRest...>::value
    };
};

template<std::size_t V> class
Test
{
    public:
    Test() {}

    template <typename... TArgs>
    Test(TArgs && ... args) 
    {
        static_assert
        (
            sizeof...(TArgs) == V
        ,   "arguments count mismatch"
        );
        static_assert
        (
            contains_only_array_of_3_int<::std::decay_t<TArgs>...>::value
        ,   "arguments type mismatch"
        );
    }
};

int main()
{
    Test<1> t
    {
        ::std::array<int, 3>{ 1, 2, 3 }
    };
    Test<2> t2
    {
        ::std::array<int, 3>{ 1, 2, 3 }
    ,   ::std::array<int, 3>{ 4, 5, 6 }
    };
    Test<3> t3
    {
        ::std::array<int, 3>{ 1, 2, 3 }
    ,   ::std::array<int, 3>{ 4, 5, 6 }
    ,   ::std::array<int, 3>{ 7, 8, 9 }
    };
    Test<3> t3_args_count_fail
    {
        ::std::array<int, 3>{ 1, 2, 3 }
    ,   ::std::array<int, 3>{ 4, 5, 6 }
    };
    Test<3> t3_args_tupe_fail
    {
        ::std::array<int, 3>{ 1, 2, 3 }
    ,   ::std::array<int, 2>{ 4, 5 }
    ,   ::std::array<int, 3>{ 7, 8, 9 }
    };
    return(0);
}

online editor