【问题标题】:std::shared_ptr 中派生类的模板规范
【发布时间】:2022-01-23 11:36:44
【问题描述】:

在这种简单的情况下,假设Base 无法更改,我将如何为Derived 类提供模板特化 - 在我的真实代码中,Base 是一个我无法更改的库。

#include <iostream>
#include <memory>

class Base
{
    public:
        virtual void foo() { std::cout << "In base\n"; }
};

class Derived: public Base
{
    public:
        virtual void foo() { std::cout << "In derived\n"; }
};

template<typename T>
void wibble(T &&baz)
{
    std::cout << "In wibble for default\n";
    baz->foo();
}

// How do I provide a specialisation here?
//template<typename what_goes_here>
//void wibble(what_goes_here &&baz)
//{
//    std::cout << "In wibble for derived\n";
//    baz->foo();
//}

int main()
{
    std::shared_ptr<Base> bar = std::make_shared<Derived>();
    
    bar->foo();
    wibble(bar);

    return 0;
}

当共享指针中包含的实际类型为Derived 时,我希望能够使用单独的模板。

【问题讨论】:

  • 在代码中你有一个shared_ptr&lt;Base&gt; 的实例。它指向Derived 的事实在技术上是运行时信息。所以你不能在编译时消除两者的歧义。您可以调用运行时动态转换来确定什么是什么,但仅此而已。
  • 您不能根据shared_ptr 的运行时类型专门化模板。如果wibble 无法修改,那么您将无能为力。

标签: c++ templates c++14


【解决方案1】:

这里的正确工具是使用dynamic_cast。这是运行时信息,因此必须在运行时查询。

类似

void wibble(std::shared_ptr<Base*> baz){
    if(auto derived =dynamic_cast<Derived*>(baz.get())){
       // user derived pointer.
    }
}

应该能让你实现与你想要的相似的东西。 如果您的键盘缺少 *,您也可以(感谢 Eljay)

if(auto derived = std::dynamic_pointer_cast<Derived>(baz)){
    // use derived
}

这只是模板和多态不能很好地相互配合的另一种情况,主要是因为编译时/运行时的二分法。

【讨论】:

猜你喜欢
  • 2018-02-25
  • 2016-02-24
  • 1970-01-01
  • 1970-01-01
  • 2014-10-13
  • 1970-01-01
  • 2016-02-17
  • 2015-04-10
  • 2017-06-24
相关资源
最近更新 更多