使用变量

时间:2016-05-19 14:33:50

标签: c++ templates const template-specialization

我在一个类中有三个指针,每个指针都是模板化结构的实例。我试图使用get<>()方法检索其中任何一个,其返回类型相应地不同。

//Example program
#include <iostream>
#include <map>
#include <string>
#include <boost/shared_ptr.hpp>
#include <boost/variant.hpp>
#include <boost/any.hpp>
class CBase {};
enum en {Aa = 1, Bb = 2, Cc = 3};
class A {
    public: 
    template<en dim>
    struct C : public CBase, boost::static_visitor<CBase *>{
        int x;
        C() {
          x = dim;
        }
        template <en t>
        CBase * operator()(C<t> *s) const {
          return s;
        }
    };

    C<Aa>* Aasd;
    C<Bb>* Bbsd;
    C<Cc>* Ccsd;
    std::map<en, boost::variant<C<Bb> *, C<Aa> *, C<Cc> * > > matrices;    

    A() {
        Aasd = new C<Aa>;
        Bbsd = new C<Bb>;
        Ccsd = new C<Cc>;
    matrices.insert(std::make_pair(Bb, Bbsd));
    matrices.insert(std::make_pair(Aa, Aasd));
    matrices.insert(std::make_pair(Cc, Ccsd));
   }

   template<en tt>
    C<tt>* get() {
     return static_cast<C<tt> *>(boost::apply_visitor(C<tt>(), matrices[tt]));   
    }

    ~A() {
     delete Aasd;
     delete Bbsd;
     delete Ccsd;
    }        
};

    template<>
    A::C<Aa>* A::get<Aa>() {
               return static_cast<C<Aa> *>(boost::apply_visitor(C<Aa>(), matrices[Aa]));
    }

    template<>
    A::C<Bb>* A::get<Bb>() {
               return static_cast<C<Bb> *>(boost::apply_visitor(C<Bb>(), matrices[Bb]));
    }

    template<>
    A::C<Cc>* A::get<Cc>() {
               return static_cast<C<Cc> *>(boost::apply_visitor(C<Cc>(), matrices[Cc]));
    }

int main()
{    
  A a;

  int i = 0;
  en samp = Aa;
  std::cout<<a.get<Aa>()->x<<std::endl; // This runs fine
  //std::cout<<a.get<samp>()->x<<std::endl; // This throws error: the value of 'samp' is not usable in a constant expression
  return 0;
}

我明白我需要指定一个编译时常量来实例化一个模板。但是,在我的情况下,我想使用一个变量来检索任何一个指针。任何有关如何做到这一点的想法或建议都将受到高度赞赏。

编辑:

我正在寻找替代建议来检索这三个指针Aasd,Bbsd,Ccsd的'x'成员,就像在main函数中一样,即使我必须完全删除模板。应该可能是

en samp = Aa;
a.get(samp)->x = 6;
samp = Bb;
a.get(samp)->x = 5;

en samp = Aa;
a[samp]->x = 6;
samp = Bb;
a[samp]->x = 5;

2 个答案:

答案 0 :(得分:1)

samp保持不变:

const en samp;

编辑: 为什么有效:

因为

非类型模板参数必须是常量表达式(在编译时已知)

证明: N3337 14.3.2 / 1

  

非类型的模板参数,非模板模板参数应为之一:

     

...

     
      
  • 对于非类型模板参数的整数或枚举类型,转换后的常量表达式类型为模板参数;或
  •   
     

...

什么时候是枚举类型变量常量表达式?

N3337 5.19 / 2:

  

条件表达式是核心常量表达式,除非它可能涉及以下之一   评估子表达式

     

...

     
      
  • 左值 - 右值转换(4.1),除非它适用于      
        
    • 一个整数或枚举类型的glvalue,它引用一个带有前一个的非易失性 const对象   初始化使用常量表达式
    • 进行初始化   
  •   
     

...

因为如果:

const en samp = Aasamp指的是用常量表达式

初始化的const对象

答案 1 :(得分:0)

x移至CBase,然后从CBase *而不是get返回C<T> *。这将至少解决返回值的问题,允许调用代码轻松访问->x

然后你可以得到一个像这样的简单方法(未经测试):

CBase* A::get(en x) {
    switch(x) {
        break; case Aa: return this->get<Aa>();
        break; case Bb: return this->get<Bb>();
        break; case Cc: return this->get<Cc>();
    }
}