使用模板参数包而不是宏

时间:2017-10-08 21:22:39

标签: c++ c++11 templates variadic-templates typetraits

我正在阅读Andrei Alexandrescu的现代C ++设计,我正在尝试使用他给出的一些类型列表示例。在下面的示例中,我想创建一个包含类型和整数的Option结构的列表。稍后我想创建这些选项的类型列表,然后将其与整数一起传递给另一个结构FindTypeForMapping。如果整数与选项列表中设置的任何整数匹配,则表达式应评估为该选项的类型,否则它应评估为我的自定义类型NullType

有效的第一种方法是使用宏创建OptionsList,并且我有列表所包含的每个Option个数的宏,其中n {的每个宏都有{ {1}}正在使用Option n-1 s。

的宏

然后我想在模板参数中使用参数包到列表中。此版本的列表名为Option。在OptionsList2中,我以递归方式构建列表,但在将此列表传递给OptionsList2时,我收到编译时错误(见下文)。

FindTypeForMapping

1 个答案:

答案 0 :(得分:1)

抱歉,但是......为什么不简单地使用std::tuple代替变量OptionList2

您的FindTypeForMapping类型特征可以简单地写为(对不起,如果我在FTFM中缩写名称)

template <typename, int>
struct FTFM;

template <int n, int no, typename TypeO, typename ... Ts>
struct FTFM<std::tuple<Option<no, TypeO>, Ts...>, n>
 { using type = typename FTFM<std::tuple<Ts...>, n>::type; };

template <int n, typename TypeO, typename ... Ts>
struct FTFM<std::tuple<Option<n, TypeO>, Ts...>, n>
 { using type = TypeO; };

template <int n>
struct FTFM<std::tuple<>, n>
 { using type = NullType; };

以下是一个完整的工作(以及......编译)示例

#include <tuple>
#include <type_traits>

struct NullType
 { };

template <int n, typename T>
struct Option : public std::integral_constant<int, n>
 { using type = T; };

template <typename, int>
struct FTFM;

template <int n, int no, typename TypeO, typename ... Ts>
struct FTFM<std::tuple<Option<no, TypeO>, Ts...>, n>
 { using type = typename FTFM<std::tuple<Ts...>, n>::type; };

template <int n, typename TypeO, typename ... Ts>
struct FTFM<std::tuple<Option<n, TypeO>, Ts...>, n>
 { using type = TypeO; };

template <int n>
struct FTFM<std::tuple<>, n>
 { using type = NullType; };

template <typename T, int I>
using FTFM_t = typename FTFM<T, I>::type;

int main ()
 {
   using  opt0 = Option<0, void>;
   using  opt1 = Option<1, char>;
   using  opt2 = Option<2, short>;
   using  opt3 = Option<3, int>;
   using  opt4 = Option<4, long>;
   using  opt5 = Option<5, long long>;

   using  optList = std::tuple<opt0, opt1, opt2, opt3, opt4, opt5>;

   static_assert ( std::is_same<void,      FTFM_t<optList, 0>>{}, "!" );
   static_assert ( std::is_same<char,      FTFM_t<optList, 1>>{}, "!" );
   static_assert ( std::is_same<short,     FTFM_t<optList, 2>>{}, "!" );
   static_assert ( std::is_same<int,       FTFM_t<optList, 3>>{}, "!" );
   static_assert ( std::is_same<long,      FTFM_t<optList, 4>>{}, "!" );
   static_assert ( std::is_same<long long, FTFM_t<optList, 5>>{}, "!" );
   static_assert ( std::is_same<NullType,  FTFM_t<optList, 6>>{}, "!" );
 }