(This question得到Nim的回答,其中提及boost::mpl::map。)
标准C ++中是否有可以容纳类型的编译时容器?
用法示例如下:
compiler::vector foo{char, short, long, long long};
template <int N>
void bar(foo[N] param){/*do something and return foo[N]*/}
答案 0 :(得分:3)
在c ++ 11中,您可以使用std :: tuple :(免责声明:未测试)
#include <tuple>
#include <type_traits>
std::tuple<char, short, long, long long> foo;
// reference type
template <int N>
void bar(decltype(std::get<N>(foo)) param){...}
// value type
template <int N>
void bar(std::remove_reference<decltype(std::get<N>(foo))>::type param)
请注意,这并不完全是您想要的,因为您将只有值或引用类型,即使两者都在foo的元组声明中混合。
永远不会使用元组的值。我认为通过编译器优化,foo实际上永远不会在目标代码中实现
答案 1 :(得分:3)
作为类型容器,标准为您提供std::tuple
和 - 如bogdan所评论 - 您可以使用std::tuple_element
访问类型元素。
using foo = std::tuple<char, short&, const long&&, long long>;
template <int N>
typename std::tuple_element<N,foo>::type bar(){/*...*/}
即使std::tuple_element
不存在,您也可以轻松构建自己的:
/// We want a metafunction to accept an index N into our type list LIST
template <unsigned N, typename LIST> struct
tuple_element;
/// Specialization for the case where N==0
template <template <typename ...> class LIST_T,typename T,typename...ELMS> struct
tuple_element<0,LIST_T<T,ELMS...>> {
using type = T; // just take the first type from the list
};
template <unsigned N, template <typename ...> class LIST_T,typename T,typename...ELMS> struct
tuple_element<N,LIST_T<T,ELMS...>> {
/// fallback for N>0: delegate the result type recursively until N->0
using type = typename tuple_element<N-1,LIST_T<ELMS...>>::type;
};
// create a convenience wrapper for the template
template <unsigned N, typename LIST> using
type_at = typename tuple_element<N, LIST>::type;
现在您可以定义类型列表,例如像这样:
using foo = std::tuple<char, short&, const long&&, long long>;
您可以使用type_at<N, foo>
轻松访问它的元素:
static_assert(std::is_same< type_at<0,foo>, char>::value,"error");
static_assert(std::is_same< type_at<1,foo>, short&>::value,"error");
static_assert(std::is_same< type_at<2,foo>, const long&&>::value,"error");
static_assert(std::is_same< type_at<3,foo>, long long>::value,"error");
template <int N>
type_at<N,foo> bar(){/*...*/}
答案 2 :(得分:0)
这个版本是基于Bérenger的回答,它让我了解tuple
概念。但我相信我们可以做得更好,甚至保留参考文献:
tuple foo<char&, short&, long&, long long&>;
template <int N>
void bar(tuple_element_t<N, decltype(foo)> param){}
事实上,如果没有计划在此函数之外使用foo
,我们甚至可以将其声明为内联:
template <int N>
void bar(tuple_element_t<N, tuple<char&, short&, long&, long long&>> param){}