基于模板参数的条件编译时包含/排除代码?

Xeo*_*Xeo 25 c++ templates conditional-compilation compile-time

考虑以下类,将内部结构Y用作类型,例如.在模板中,稍后:

template<int I>
class X{
  template<class T1>
  struct Y{};

  template<class T1, class T2>
  struct Y{};
};
Run Code Online (Sandbox Code Playgroud)

现在,这个示例显然不会编译,错误是第二个X<I>::Y已经定义或者模板参数太多.
我想在没有(额外)部分特化的情况下解决这个问题,因为int I参数不是唯一的,并且它的位置可以在不同的部分特化中有所不同(我的实际结构看起来更像这样,上面只是为了简化问题),所以我想one class fits every I解决.


我的第一个想法显然是enable_if,但这似乎在我身上失败,例如.我仍然得到同样的错误:

// assuming C++11 support, else use boost
#include <type_traits>

template<int I>
class X{
  template<class T1, class = std::enable_if<I==1>::type>
  struct Y{};

  template<class T1, class T2, class = std::enable_if<I==2>::type>
  struct Y{};
};
Run Code Online (Sandbox Code Playgroud)

所以,既然enable_if失败了,我希望还有另一种方法来实现以下编译时检查:

template<int I>
class X{
  __include_if(I == 1){
    template<class T1>
    struct Y{};
  }

  __include_if(I == 2){
    template<class T1, class T2>
    struct Y{};
  }
};
Run Code Online (Sandbox Code Playgroud)

这只是为了节省我很多代码重复,但如果它在某种程度上可能会让我感到高兴.
编辑:可悲的是,我不能使用显而易见的:可变参数模板,因为我使用的是Visual Studio 2010,因此我只能使用支持的C++ 0x内容.:/

Pot*_*ter 8

这里有两个问题:

  1. enable_if 适用于部分专业化,而不是主要模板.
  2. 外部可见参数的数量由主模板确定,其中可能只有一个.

答案1.

正如您在聊天中所建议的,模板的链接列表可以模拟可变参数包.

template<int I>
class X{
  template<class list, class = void>
  struct Y;

  template<class list>
  struct Y< list, typename std::enable_if<I==1>::type > {
      typedef typename list::type t1;
  };

  template<class list>
  struct Y< list, typename std::enable_if<I==2>::type > {
      typedef typename list::type t1;
      typedef typename list::next::type t2;
  };
};
Run Code Online (Sandbox Code Playgroud)

如果你最终得到next::next::next垃圾,很容易编写一个元函数,或者使用Boost MPL.


答案2.

不同的arity模板可以相似地命名,但如果它们嵌套在SFINAE控制类型中,则仍然保持不同.

template<int I>
class X{
  template<typename = void, typename = void>
  struct Z;

  template<typename v>
  struct Z< v, typename std::enable_if<I==1>::type > {
      template<class T1>
      struct Y{};
  };

  template<typename v>
  struct Z< v, typename std::enable_if<I==2>::type > {
      template<class T1, class T2>
      struct Y{};
  };
};

X<1>::Z<>::Y< int > a;
X<2>::Z<>::Y< char, double > b;
Run Code Online (Sandbox Code Playgroud)