我有一个类似的问题 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/