条件编译时包含/排除基于模板参数的代码? [英] Conditional compile-time inclusion/exclusion of code based on template argument(s)?

查看:124
本文介绍了条件编译时包含/排除基于模板参数的代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑下面的类,内部结构 Y 被用作类型,例如。在模板中,稍后:

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

template< class T1,class T2>
struct Y {};
};

现在,这个例子显然不会编译,错误的第二个 X< I> :: Y 已经被定义或者它具有太多的模板参数。

我想解决没有(额外)部分专门化,因为 int I 参数不是唯一的一个,它的位置可以在不同的部分专业化中不同(我的实际结构看起来更像这样,以上只是为了简单的问题),所以我想一个类适合每个解决方案。 p>




我的第一个想法显然是 enable_if ,但似乎失败了我,例如。我仍然得到相同的错误:

  //假设C ++ 11支持,否则使用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 {};
};






因此,由于 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 {};
}
};






很多的代码重复,但我会真的很高兴,如果它是某种可能的。

编辑:可悲的是,我不能使用明显的:variadic模板,因为我使用Visual Studio 2010,所以只有C ++ 0x东西在那里支持我可以使用。 :/

解决方案

这里有两个问题:


  1. enable_if 适用于部分特化,而不适用于主要范本。

  2. 外部可见参数的数量由


  3. 回答1。



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

      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;
    };
    };

    如果结果是 next :: next :: next 垃圾,很容易写一个元函数,或使用Boost MPL。






    >

    不同的模板可以命名类似,但如果它们嵌套在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>一个;
    X 2 :: Z<> :: Y< char,double> b;


    Consider the following class, with the inner struct Y being used as a type, eg. in templates, later on:

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

    Now, this example will obviously not compile, with the error that the second X<I>::Y has already been defined or that it has too many template parameters.
    I'd like to resolve that without (extra) partial specialization, since the int I parameter isn't the only one and the position of it can differ in different partial specializations (my actual struct looks more like this, the above is just for simplicity of the question), so I'd like one class fits every I solution.


    My first thought was obviously enable_if, but that seems to fail on me, eg. I still get the same errors:

    // 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{};
    };
    


    So, since enable_if fails, I hope there is another way to achieve the following compile time check:

    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{};
      }
    };
    


    It would just be to save me a lot of code duplication, but I'd be really happy if it was somehow possible.
    Edit: Sadly, I can't use the obvious: variadic templates, as I'm using Visual Studio 2010, so only the C++0x stuff that is supported there I can use. :/

    解决方案

    There are two problems here:

    1. enable_if works with partial specialization, not primary templates.
    2. The number of externally-visible arguments is determined by the primary template, of which there may be only one.

    Answer 1.

    As you suggested in chat, a linked list of templates can emulate the variadic parameter pack.

    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;
      };
    };
    

    If you end up with next::next::next garbage, it's easy to write a metafunction, or use Boost MPL.


    Answer 2.

    The different-arity templates can be named similarly but still stay distinct if they are nested inside the SFINAE-controlled type.

    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;
    

    这篇关于条件编译时包含/排除基于模板参数的代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆