c++ - 指向模板接口的唯一指针
问题描述
为了简单起见,我将问题简化为简单的示例。我有基类:
template<typename T>
class Base {
virtual T getParameter(T&) = 0;
};
以及使用工厂方法返回其对象的派生类:
template<typename T>
class Der : public Base<T> {
public:
static std::unique_ptr<Der> getInstance() {
return std::make_unique<Der<std::string>>();
}
T getParameter(T& param) override {
return param;
}
};
现在我想使用包含接口的 unique_ptr 传递派生类的对象,即:
template<typename T>
void someFun(std::unique_ptr<Base<T>>&& ptr) {
//do sth with ptr
}
通过调用:
someFun(Der<std::string>::getInstance());
错误:
test.cpp:26:44: error: no matching function for call to ‘someFun(std::unique_ptr<Der<std::__cxx11::basic_string<char> >, std::default_delete<Der<std::__cxx11::basic_string<char> > > >)’
someFun(Der<std::string>::getInstance());
^
test.cpp:21:6: note: candidate: template<class T> void someFun(std::unique_ptr<Base<T> >&&)
void someFun(std::unique_ptr<Base<T>>&& ptr) {
^~~~~~~
test.cpp:21:6: note: template argument deduction/substitution failed:
test.cpp:26:44: note: mismatched types ‘Base<T>’ and ‘Der<std::__cxx11::basic_string<char> >’
someFun(Der<std::string>::getInstance());
解决方案
我认为解决这个问题的最简单方法是在派生类型上创建T
in Base
、模板的别名,并使用它而不是依赖模板推导。
如果您害怕在不相关的东西中意外键入鸭子,您仍然可以Base
通过 using强制继承。std::is_base_of<>
#include <memory>
#include <typer_traits>
template<typename T>
class Base {
public:
using param_t = T;
virtual T getParameter(T&) = 0;
};
template<typename T>
class Der : public Base<T> {
public:
static std::unique_ptr<Der> getInstance() {
return std::make_unique<Der<std::string>>();
}
T getParameter(T& param) override {
return param;
}
};
template<typename DerivT>
void someFun(std::unique_ptr<DerivT> deriv_ptr) {
using T = typename DerivT::param_t;
// Just to be safe
static_assert(std::is_base_of<Base<T>, DerivT>::value, "");
// If you REALLY care about only having a base pointer:
std::unique_ptr<Base<T>> ptr(deriv_ptr.release());
//do stuff.
}
void foo() {
someFun(Der<std::string>::getInstance());
}
如果您真的想enable_if
处理someFun()
. 但是,我发现这种static_assert()
方式更清洁,所以除非必要,否则我会使用它。
推荐阅读
- c++ - 如果我在多线程中重置相同的 shared_ptr 不会崩溃
- c# - 如何在 C# 中将两个 StringCollection 合并/合并为一个
- java - Are there ways set a local variable of a function inside stream java 8
- grails - Grails 3.3.9 从服务调用 taglib
- aws-amplify - AWS AppSync Null @connection 查询结果
- c++ - 在一行中从类构造中初始化抽象类引用
- r - 使用 varlist 在 r studio 上循环
- python-3.x - 无法从 python lambda 将 XML 写入 S3
- python - 在所有 Anaconda 环境中,Spyder 在加载期间不断崩溃
- ruby-on-rails - Has_many 到 rails 中的 has_many 关系问题