(这个问题的答案由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]*/}
(这个问题的答案由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]*/}
在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
,只需要 decltype
和 declval
。 - Lightness Races in Orbitdecltype(std::get<T>(foo))
会在索引 T
处将一个意外的引用添加到类型中,因为 std::get
将返回一个引用类型。 - Julianstd::get
的返回类型,例如这里,你会发现它永远不会返回纯类型,而总是返回一个rvalue或lvalue引用。至少对我来说,以下断言没有错误:static_assert(std::is_same<int&&,decltype(std::get<0>(std::declval<std::tuple<int>>()))>::value,"error")
。 - Julianstd::get
的作用,但正如我所说,你忘记了decltype
的作用。请查看我提供的链接。将rvalue表达式命名为lvalue引用时,引用类型会被删除。你使用declval
的示例与之前的示例不同。 - Lightness Races in Orbitstd::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(){/*...*/}
这篇文章基于Bérenger的回答,他让我了解了tuple
的概念。但我相信我们可以做得更好,甚至保留引用:
tuple foo<char&, short&, long&, long long&>;
template <int N>
void bar(tuple_element_t<N, decltype(foo)> param){}
template <int N>
void bar(tuple_element_t<N, tuple<char&, short&, long&, long long&>> param){}
boost::mpl::vector
。 - Joseph Mansfielddo something and return foo[T]
是相关的,因为有一个隐含的编译时代码层面无法工作的问题。也就是说,一个函数不能返回多个类型。然而,你可以进行特化或委托给重载函数,这样就能正常工作了。 - Mooing Duck