C++多态模板类,模板类型对象的实例化

Posted

技术标签:

【中文标题】C++多态模板类,模板类型对象的实例化【英文标题】:C++ Polymorphic template class, instantiation of template type object 【发布时间】:2020-05-20 17:25:39 【问题描述】:

我有以下情况,我想实例化一个模板类型的对象。 我希望模板类型对象的实例化依赖于“实例化器”类。

template <class T>
class Base

public:
  Base()

  void do_something()
  
    T obj = this->Test();
    // do something with object
  

  virtual T Test()
  
   return T(5);
  
;


template <class T>
class Derived : public Base<T>

public:
  Derived() : Base<T>() 
  virtual T Test()
  
    return T(5, 6);
  
;

class Test1

public:
  Test1(int x)
;
class Test2 : public Test1

public:
  Test2(int x, int y) : Test1(x) 
;

稍后在我的代码中,我想使用 Base 或 Derived 对象。 它们在函数 do_something() 中对模板类型对象 (obj) 执行操作。 我想让obj的实例化依赖于实现 Test() 函数。 Base 应该只适用于 Test1 类型的对象或具有相同构造函数的 Test1 的派生类。 Derived 应该只适用于与 Test2 具有相同构造函数的对象。

Base<Test1>(); // works
Base<Test2>(); // doesn't work, but should not work by my design and throw a compile error
Derived<Test1>(); // same
Derived<Test2>();  // should work, but doesn't,
// since Base::Test() still exists, but cannot be compiled due to wrong constructor of T

有没有办法实现所描述的行为? 或者我可以进行设计更改吗?

【问题讨论】:

坦率地说,您的代码中充满了拼写错误。目前尚不清楚该代码应该实现什么。请解释它或给出一个输出示例并告诉我们所需的输出 请提供minimal reproducible example。你修正了一些错别字,但还是太多了。 你是对的,我在快速写问题时犯了很多错别字。我已经修复了它们并写了我想要的行为的一个小解释。 【参考方案1】:

对于任何T,您可以将 Base 更改为正确:

template <class T>
class Base

public:
    Base()

    void do_something()
    
        T obj = this->Test();
        // do something with object
    

    virtual T Test()
    
        if constexpr (std::is_constructible_v<T, int>) 
            return T(5);
        
        throw std::runtime_error("should not be called");
    
;

但是

Base&lt;Test2&gt;(); 会编译但会在运行时抛出。

拆分并派生两个似乎更好:

template <class T>
class Base

public:
    Base() = default;
    virtual ~Base() = default;

    void do_something()
    
        T obj = this->Test();
        // do something with object
    

    virtual T Test() = 0;
;

template <class T>
class Derived : public Base<T>

public:
  Derived() : Base<T>() 
  T Test() override  return T(4); 
;

template <class T>
class Derived2 : public Base<T>

public:
  Derived() : Base<T>() 
  T Test() override  return T(5, 6); 
;

【讨论】:

感谢您的回答。这似乎是一个很好的解决方案。抽象基础也是一个好主意。我最初希望Derived 可以与相同的模板类型完全互换,但这永远不会奏效。我的意思是,我的示例甚至被设计为不允许这样做。所以我可能会使用你的解决方案。

以上是关于C++多态模板类,模板类型对象的实例化的主要内容,如果未能解决你的问题,请参考以下文章

派生模板类对象的实例化

C++模板详解

C++模板详解:泛型编程模板原理非类型模板参数模板特化分离编译

C++模板详解:泛型编程模板原理非类型模板参数模板特化分离编译

C++模板

C++ 模板详解(转)