将动态参数转发给构造函数

时间:2016-02-21 14:58:59

标签: c++ wrapper c++14 variadic-templates

这是一个跟进问题: std::initializer_list as std::array constructor

我从那里得到的答案中学到了一点,并尝试扩展我的包装类。简而言之,这个问题,我的解决方案以及它的问题。

问题: 我需要一个从模板创建数组的类,没有默认构造函数和未知数量的参数。它本身可以使用可变参数模板包装在其他类中。

我的解决方案:工作但不是真正的用户友好因此我希望有一些想法来改进它 Running example

class a   // some sort of storage class that need wrapper for more functions
{
public:     
   a(int c)
    {
        std::cout << "Class A: " << c << std::endl;
    }
};

template<class TStack>
class b : public TStack  // wrapper with char input
{
public:
    template<class ... TArgs>
    b(char c, TArgs&& ... args)
        : TStack( std::forward<TArgs>(args)...)
    {
        std::cout << "Class B: " << c << std::endl;
    }
};

template<class TStack, unsigned int TBin>
class c  // array wrapper
{
private:

    template<class TStack>
    class d : public TStack   // tuple Expansion
    {
    private:

        template <class ... TArgs, std::size_t... Is>
        d(std::tuple<TArgs...> args, std::index_sequence<Is...>)
            : TStack(std::get<Is>(args)...)
        {}

    public:
        template<class ... TArgs>
        d(std::tuple<TArgs...> args)
            : d(args, std::make_index_sequence< sizeof...(TArgs) >{})
        {}
    };

    std::array< d<TStack>, TBin> data;

    template <class TArgs, std::size_t... Is>
    c(std::initializer_list< TArgs > il, std::index_sequence<Is...>)
        : data{ { *(il.begin() + Is)... } }
    {
    }

public: 
    template<class TArgs>
    c(std::initializer_list< TArgs > il)
       : c(il, std::make_index_sequence<TBin>{})
    {}
};

int main()
{

    a(1);
    b<a>('a', 3);

    c<a, 3>({ std::make_tuple(4), std::make_tuple(5), std::make_tuple(6)});  
    b< c<a, 4> >('a', std::initializer_list<std::tuple<int>>{std::make_tuple(7), std::make_tuple(8), std::make_tuple(9), std::make_tuple(10)}); 

    c< b<a>, 4>({ std::make_tuple('A', 11), std::make_tuple('B', 12), std::make_tuple('C', 13), std::make_tuple('D', 14) });
    b< c< b<a>, 4>>('z', std::initializer_list<std::tuple<char, int>>{ std::make_tuple('A', 11), std::make_tuple('B', 12), std::make_tuple('C', 13), std::make_tuple('D', 14) });
}

为什么我不喜欢我的解决方案: 该代码工作正常,但每个列表前面的std::initializer_list<std::tuple</*lot of types*/>>并不是我希望的最友好的用户方式。 make_tuple可以,但会大大降低大型列表的可读性。

此致 Matyro

0 个答案:

没有答案