c++ - CRTP vs. 基类 vector

标签 c++ templates inheritance crtp

我有一个类似的问题 C++ vector of CRTP shared pointers但我的问题表述增加了一个事实,即我想用于所有继承类的函数的返回类型是模板化的。

详细来说,让我们假设:

template <class Derived>
class Base {
    Derived Value() const {
        return static_cast<Derived>(this->Value());
    };
};

class ChildDouble : public Base<ChildDouble> {
  public:
    ChildDouble(double r) : _value(r){};

    double Value() const {
        return _value;
    };

  private:
    double _value;
};

class ChildString : public Base<ChildDouble> {
  public:
    ChildString(string s) : _value(s){};

    string Value() const {
        return _value;
    };

  private:
    string _value;
};

目标是使用它有点类似于以下主要内容

void main() {


    std::vector<Base*> vec;
    vec.push_back(new ChildDouble(3.0));
    vec.push_back(new ChildString("Thomas"));

    unsigned counter = 0;
    for (const auto& e : vec) {
        std::cout << "Entry " << counter << " : " << e->Value()
                  << std::endl;
        counter++;
    }

}


编译器显然对此不满意,因为 Base需要一个模板参数。

任何想法如何解决这个问题?我在这里使用 CRTP 虽然我不应该使用它吗?

最佳答案

虚拟方法(这是在没有 CRTP 的情况下正常工作所需要的)在这里不起作用,因为 Value() 的接口(interface)不同。在每个派生类型中。虚拟继承依赖于每个人都相同的签名,除了在一些特殊情况下,比如协变返回类型。它也不起作用,因为虚拟方法不能被模板化。

但是,您可以使用 std::variant动态调度你不兼容的接口(interface),因为它是基于模板的。首先,为您的变体定义一个方便的别名:

using Child = std::variant<ChildDouble, ChildString>;

然后使用,发送 std::visit和一个通用的 lambda:

std::vector<Child> vec;
vec.push_back(ChildDouble(3.0));
vec.push_back(ChildString("Thomas"));

unsigned counter = 0;
for (const auto& e : vec) {
    std::visit([&counter](auto&& v) { 
        std::cout << "Entry " << counter << " : " << v.Value()
                << std::endl;
    }, e);

    counter++;
}    

演示:https://godbolt.org/z/bENWYW

关于c++ - CRTP vs. 基类 vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59533988/

相关文章:

带有行尾的 C++ 字符串用于归档空行

entity-framework - Entity Framework : Inheritance and Include

c++ - 无法访问 C++ 中类模板继承第二级上的 protected 类成员

c++ - 如何避免复制回调函数 (C++)

c++ - "String.h"VS <字符串.h>

c++ - 递归定义元组

C++:继承与。包含模板类

c++ - 不能在函数声明中使用模板参数

c# - 当我们仍然可以在抽象类中使用抽象属性时,它们的目的是什么?

c++ - char 和 wchar_t 的模板没有给出匹配的成员