如何使用指定数量的元素(相同类型)创建boost :: tuple?

Jas*_*n R 6 c++ boost boost-mpl template-meta-programming

假设我有以下类定义:

template <unsigned int N>
class foo
{
    boost::tuples::tuple<...> bar;
};
Run Code Online (Sandbox Code Playgroud)

给定编译时常量N,我想将类型扩展为bar包含N指定类型元素的元组.也就是说,类型foo<2>::barboost::tuples::tuple<T, T>.我猜我可以使用Boost.MPL,但我还没有想出确切的序列.我想我能做到:

template <typename T, int N>
struct type_repeater
{
    typedef typename boost::mpl::fold<
        boost::mpl::range_c<T, 0, N>,
        boost::mpl::vector<>,
        boost::mpl::push_back<_1, T>
    >::type type;
};
Run Code Online (Sandbox Code Playgroud)

所以那么例如type_repeater<T, 2>::type相当于boost::mpl::vector<T, T>.我只是不确定如何/如果我可以采取该类型列表并将其注入元组的参数列表,就像我想要的那样.这可能吗?

Omn*_*ity 5

这似乎是使用C++ 11的一个很好的最小例子

#include <tuple>
template <unsigned int N, typename T>
struct type_repeater {
  typedef decltype(std::tuple_cat(std::tuple<T>(), typename type_repeater<N-1, T>::type())) type;
};

template <typename T>
struct type_repeater<0, T> {
  typedef decltype(std::tuple<>()) type;
};

int main() {
  type_repeater<3, float>::type asdf;
  std::get<0>(asdf);
  std::get<1>(asdf);
  std::get<2>(asdf);
}
Run Code Online (Sandbox Code Playgroud)


mpa*_*ark 3

虽然这对于可变参数模板是完全可行的std::tuple,但我认为最好的解决方案就是使用std::array. 如果您只想要一个包含 N 个 T 实例的容器,则std::array签名已经是template <typename T, std::size_t N> class array。我认为它完全符合您的需求。

话虽如此,如果你确实std::tuple出于某种原因想要这样做,你可以这样做:

#include <tuple>

/* Forward declaration. */
template <std::size_t N, typename T>
class Tuple;

/* Convenience type alias. */
template <std::size_t N, typename T>
using TTuple = typename Tuple<N, T>::type;

/* Base case. */
template <typename T>
class Tuple<0, T> {
  public:

  using type = std::tuple<>;

}; // Tuple<0>

/* Recursive case. */
template <std::size_t N, typename T>
class Tuple {
  public:

  /* Note the use of std::declval<> here. */
  using type = decltype(std::tuple_cat(std::declval<std::tuple<T>>(),
                                       std::declval<TTuple<N - 1, T>>()));

};  // Tuple<N, T>

/* std::declval<> is necessary to support non default constructable classes. */
class NoDefault {
  public:

  NoDefault() = delete;

};  // Foo

/* Sample use. */
static_assert(std::is_same<TTuple<2, NoDefault>,
                           std::tuple<NoDefault, NoDefault>>::value, "");

int main() {}
Run Code Online (Sandbox Code Playgroud)

注意:如果您无法访问 C++11,但可以访问 boost,boost::array并且boost::tuples::tuple可以很好地代替std::arraystd::tuple