假设我有以下类定义:
template <unsigned int N>
class foo
{
boost::tuples::tuple<...> bar;
};
鉴于编译时常量N
,我想将bar
的类型扩展为包含指定类型的N
元素的元组。也就是说,foo<2>::bar
的类型为boost::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;
};
然后,例如type_repeater<T, 2>::type
将等同于boost::mpl::vector<T, T>
。我只是不确定如何/如果我可以采取该类型列表并将其注入元组的参数列表,就像我想要的那样。这可能吗?
答案 0 :(得分: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);
}
答案 1 :(得分: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() {}
注意:如果您无法访问C ++ 11但有权获得提升权限,则boost::array
和boost::tuples::tuple
可以代替{{std::array
1}}和std::tuple
。
答案 2 :(得分:1)
由于你明确要求一种方法将mpl :: vector放入运行时容器中,我建议你保持Boosty并使用Fusion的as_vector:
给出你初始的例子,你在mol :: fold中得到一个mpl :: vector,然后你会使用:
boost::fusion::result_of::as_vector<
mpl::vector<T, T>
>::type;
获得Fusion Vector,这似乎是你想要的。 Boost Fusion填补了编译时和运行时世界之间的空白。
此外,这是预先C ++ 11,它在许多(可能是大多数?)项目中仍然很重要。