C++虚拟模板方法

Vin*_*ent 35 c++ virtual templates

我有一个抽象类(我知道它不会以这种方式编译,但它是为了理解我想要做的事情):

class AbstractComputation {
    public:
        template <class T> virtual void setData(std::string id, T data);
        template <class T> virtual T getData(std::string id);
};

class Computation : public AbstractComputation {
    public:
        template <class T> void setData(std::string id, T data);
        template <class T> T getData(std::string id, T data);
};
Run Code Online (Sandbox Code Playgroud)

因此,当我打电话时,setData<double>("foodouble", data)我希望将foodouble(由此处不是主要关注的内部机制)识别的双精度设置为双精度数据.

那怎么办呢?

我认为通过输入类似的东西可能有一个意思,virtual void setData<double>(std::string id, double data)但我不知道该怎么做.

Dav*_*eas 53

问题是你不能轻易地将静态时间多态(模板)与运行时多态混合.在您的示例中禁用特定构造的语言的原因是可能有无限的不同类型可以实例化您的模板成员函数,这反过来意味着编译器必须生成代码以动态分派那些类型,是不可行的.

这里可以通过不同的方式来解决限制,基本上要么取消静态或动态多态.从等式中删除动态多态可以通过提供一个非派生类型来存储<key,value>映射,然后提供仅在基本级别解析的模板来完成:

class AbstractComputation {
public:
   template <typename T>
   void setData( std::string const & id, T value ) {
      m_store.setData( id, value );
   }
   template <typename T>
   T getData( std::string const & id ) const {
      return m_store.getData<T>( id );
   }
protected:
   ValueStore m_store;
};
Run Code Online (Sandbox Code Playgroud)

现在派生类可以ValueStore从基类访问,并且不需要多态.(这也可以通过直接实现功能来完成,AbstractComputation但分离问题可能是有意义的)

另一种选择是维护运行时多态性,但删除静态多态.这可以通过在基类上执行类型擦除然后调度到采用类型擦除的参数的适当(非模板化)函数来完成.最简单的版本就是使用boost::any:

class AbstractComputation {
public:
   template <typename T>
   void setData( std::string const & id, T value ) {
      setDataImpl( id, boost::any( value ) );
   }
   template <typename T>
   T getData( std::string const & id ) const {
      boost::any res = getDataImpl( id );
      return boost::any_cast<T>( res );
   }
protected:
   virtual void setDataImpl( std::string const & id, boost::any const & value ) = 0;
   virtual boost::any getDataImpl( std::string const & id ) const = 0;
};
Run Code Online (Sandbox Code Playgroud)

如何在引擎盖下实现类型擦除是有趣的,但是在这里的范围之外,重要的部分是a boost::any是一个具体的(非模板化)类型,它可以通过在参数上使用类型擦除来内部存储任何类型,并且同一时间允许类型安全地检索数据.


Tob*_*obi 14

在某些情况下,将模板从方法级别移动到类级别可能就足够了,例如:

#include <iostream>

template<typename T>
class AbstractComputation {
public:
    virtual void setData(std::string id, T data)
    {
        std::cout << "base" << std::endl;
    }
};

template<typename T>
class Computation : public AbstractComputation<T> {
public:
    virtual void setData(std::string id, T data)
    {
        std::cout << "derived" << std::endl;
    }
};

int main()
{
    AbstractComputation<int> *x = new Computation<int>();

    x->setData("1", -1);

    delete x;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)