基于参数

时间:2016-08-21 19:04:17

标签: c++ templates c++11 variadic-templates enable-if

我想要做的是能够根据参数的值对同一模板类进行不同的声明,如下所示:

// Enable if X == 2
template <int X, int W, typename Y,
          typename A = int, typename B = int> struct Z {}; 

// Enable if X != 2
template <int X,        typename Y,
          typename A = int, typename B = int> struct Z {};

我可以从这样的事情开始:

template <int X, int W, typename Y, typename A = int, typename B = int, 
          typename = std::enable_if_t<X == 2>> struct Z {};
template <int X,        typename Y, typename A = int, typename B = int,
          typename = std::enable_if_t<X != 2>> struct Z {};

问题在于,可以理解的是,它已经用不同数量的参数重新声明了它。

可变参数模板功能可以派上用场,但不幸的是,它只支持类型而不支持文字,就像在这种情况下一样。

template <typename... Args> struct Z {};
template <int X, int W, typename Y,
          typename A = int typename B = int> struct Z<X, W, Y> {};
  

类型/值不匹配 - &gt;期待一种类型,得到'X / W'

有人有解决方案吗?

修改

很抱歉我之前没有提及,但遗憾的是我无法更改参数的顺序,因为Y之后的其他参数都有默认值。

4 个答案:

答案 0 :(得分:2)

你说你想做的就像你在这里的评论所说:

// Enable if X == 2
template <int X, int W, typename Y, typename A=int, typename B=int> 
struct Z {}; 

// Enable if X != 2
template <int X,        typename Y, typename A=int, typename B=int> 
struct Z {};

显然,您希望在X !=2时没有第二个模板参数。您可以在没有名称的情况下定义它。

部分专业化可用于进行选择:

// PRIMARY TEMPLATE: Used if X != 2
template <int X, int, typename Y, typename A=int, typename B=int> 
                //^^ see here
struct Z {};

// PARTIAL SPECIALIZATION: Used if X == 2
template <int W, typename Y, typename A, typename B> 
struct Z<2, W, Y, A, B> {}; 

编辑1的2: (根据您的评论)

  

我希望能够仅使用两个参数(if X!=2)来使用结构Z:Z<3, int>

您必须重新排序模板并使用主模板中的默认参数

// PRIMARY TEMPLATE: Used if X != 2
template <int X, typename Y, int=0, typename A=int, typename B=int> 
                             //^^ see here
struct Z {};

// PARTIAL SPECIALIZATION: Used if X == 2
template <typename Y, int W, typename A, typename B> 
struct Z<2, Y, W> {}; 

您可以使用as:

Z<2, int> z;
Z<3, int, 5> z3;

编辑2的2: (对您的问题编辑和评论)

用你的话来解释:

  

我希望能够在不重新排序模板的情况下执行Z<3, int>   参数

如果第二个模板参数是类型 并且,其他参数为,则您只能执行Z<3, int>Z<2, int, ...>之类的操作拖欠。不幸的是,那不是你的情况。如果这确实是你的问题,那么你在这里走到了尽头。

答案 1 :(得分:1)

如果您可以使用C ++ 14并且您可以接受将您的整数包裹在std::integer_sequence中,则可以通过这种方式定义Z的两个版本

#include <iostream>
#include <utility>

template <typename, typename>
struct Z;

template <int W, typename T>
struct Z<std::integer_sequence<int, W>, T>
 { static constexpr int c { 0 }; };

template <int X, typename T>
struct Z<std::integer_sequence<int, 2, X>, T>
 { static constexpr int c { 2 }; };

int main()
 {
   Z<std::integer_sequence<int, 0>, long>     z0;
   Z<std::integer_sequence<int, 2, 7>, long>  z2;
   Z<std::integer_sequence<int, 2>, long>     zX;  // unacceptable ?

   std::cout << "z0: " << z0.c << std::endl;  // output: z0: 0
   std::cout << "z2: " << z2.c << std::endl;  // output: z2: 2
   std::cout << "zX: " << zX.c << std::endl;  // output: zX: 0
 }

我不知道如何将zXX == 2W定义为zX,但如果您希望z2作为Z,您可以通过以下方式定义template <typename, typename> struct Z; template <typename T, int ... I> struct Z<std::integer_sequence<int, I ...>, T> { static constexpr int c { 0 }; }; template <typename T, int ... I> struct Z<std::integer_sequence<int, 2, I ...>, T> { static constexpr int c { 2 }; };

zX

2返回Z

第二个解决方案的问题是甚至使用未定义的整数数编译 Z<std::integer_sequence<int, 0, 5, 6, 7>, long> z0; 。我的意思是编译(使用第二个解决方案)

zX

---编辑---

抱歉,我是个白痴。

简单地避免template <typename T> struct Z<std::integer_sequence<int, 2>, T>; 的定义。

在这两种情况下,您都可以声明(但不定义)以下特化。

    item: TG.BaseItem | TG.ClosedItem | any;

答案 2 :(得分:1)

如果不重新排序参数或使用其他数据结构来包装参数,那么您要做的就是不可能。

无论如何,您可以使用json: {"status":"OK" ,"count":1 ,"msg_id":"94" ,"when":"2016-08-23 11:21:01" ,"alerts":[ {"msg_id":"44" ,"title":"Medical Emergency" ,"text":"Heart Attack" ,"msg_when":"2016-08-05 14:52:03" } ] } 构造函数提交额外参数,并能够在常量表达式中使用您的类型。
举个例子:

constexpr

如果一个好的妥协主要取决于真正的问题。

答案 3 :(得分:0)

如果您可以更改模板参数的顺序,则可以专门化您的类并使用默认值:

// Chosen if X != 2
template<int X, typename Y, typename A = int, typename B = int, int = 0>
struct Z {}; // W is discarded

// Chosen if X == 2
template<typename Y, typename A, typename B, int W>
struct Z<2, Y, A, B, W> {};

Live example