来自元组的构造函数参数

MvG*_*MvG 6 c++ templates constructor c++11 stdtuple

假设我有一个模板,它由类类型和许多参数类型进行参数化.匹配这些类型的一组参数存储在元组中.如何将这些传递给类类型的构造函数?

在几乎C++ 11代码中:

template<typename T, typename... Args>
struct foo {
  tuple<Args...> args;
  T gen() { return T(get<0>(args), get<1>(args), ...); }
};
Run Code Online (Sandbox Code Playgroud)

如何...在不修复长度的情况下填充构造函数调用?

我想我可以想出一些复杂的递归模板调用机制来做到这一点,但是我不敢相信我是第一个想要这个的人,所以我想这里会有现成的解决方案. ,甚至可能在标准库中.

pan*_*nik 7

C ++ 17 std::make_from_tuple为此:

template <typename T, typename... Args>
struct foo
{
  std::tuple<Args...> args;
  T gen() { return std::make_from_tuple<T>(args); }
};
Run Code Online (Sandbox Code Playgroud)


And*_*owl 5

您需要一些模板元编程机制来实现这一目标.

实现参数调度的最简单方法是在包含打包编译时整数序列的表达式上利用包扩展.构建这样的序列需要模板机制(有关标准化此类序列的建议的更多信息,请参阅本答案末尾的注释).

假设有一个类(模板)index_range封装了一个编译时整数范围[M,N]和一个index_list封装了整数编译时列表的类(模板),这就是你如何使用它们:

template<typename T, typename... Args>
struct foo
{
    tuple<Args...> args;

    // Allows deducing an index list argument pack
    template<size_t... Is>
    T gen(index_list<Is...> const&)
    {
        return T(get<Is>(args)...); // This is the core of the mechanism
    }

    T gen()
    {
        return gen(
            index_range<0, sizeof...(Args)>() // Builds an index list
            );
    }
};
Run Code Online (Sandbox Code Playgroud)

这是一个可能的实现index_rangeindex_list:

//===============================================================================
// META-FUNCTIONS FOR CREATING INDEX LISTS

// The structure that encapsulates index lists
template <size_t... Is>
struct index_list
{
};

// Collects internal details for generating index ranges [MIN, MAX)
namespace detail
{
    // Declare primary template for index range builder
    template <size_t MIN, size_t N, size_t... Is>
    struct range_builder;

    // Base step
    template <size_t MIN, size_t... Is>
    struct range_builder<MIN, MIN, Is...>
    {
        typedef index_list<Is...> type;
    };

    // Induction step
    template <size_t MIN, size_t N, size_t... Is>
    struct range_builder : public range_builder<MIN, N - 1, N - 1, Is...>
    {
    };
}

// Meta-function that returns a [MIN, MAX) index range
template<unsigned MIN, unsigned MAX>
using index_range = typename detail::range_builder<MIN, MAX>::type;
Run Code Online (Sandbox Code Playgroud)

还要注意,Jonathan Wakely 提出了一个有趣的提议标准化一个类模板,这与我在这里所称的非常类似.int_seqindex_list


asc*_*ler 5

使用index_sequence解包一个std::tuple(或std::pairstd::array或其他任何支持的元组接口):

#include <utility>
#include <tuple>

template <typename Tuple, std::size_t... Inds>
SomeClass help_make_SomeClass(Tuple&& tuple, std::index_sequence<Inds...>)
{
    return SomeClass(std::get<Inds>(std::forward<Tuple>(tuple))...);
}

template <typename Tuple>
SomeClass make_SomeClass(Tuple&& tuple)
{
    return help_make_SomeClass(std::forward<Tuple>(tuple),
        std::make_index_sequence<std::tuple_size<Tuple>::value>());
}
Run Code Online (Sandbox Code Playgroud)

std::index_sequence并且std::make_index_sequence将在 C++1y 中。如果找不到定义它们的标头,则可以使用这些:

template <std::size_t... Inds>
struct index_sequence {
    static constexpr std::size_t size()
    { return sizeof...(Inds); }
};

template <std::size_t N, std::size_t... Inds>
struct help_index_seq {
    typedef typename help_index_seq<N-1, N-1, Inds...>::type type;
};

template <std::size_t... Inds>
struct help_index_seq<0, Inds...> {
    typedef index_sequence<Inds...> type;
};

template <std::size_t N>
using make_index_sequence = typename help_index_seq<N>::type;
Run Code Online (Sandbox Code Playgroud)

实时示例,在 C++11 模式下:http : //coliru.stacked-crooked.com/a/ed91a67c8363061b