通过智能指针和转换对基本模板参数进行模板推导
Template Deduction of Base Template Parameters through Smart Pointers and Conversion
有关完整示例,请参阅编译器资源管理器:https://godbolt.org/z/_rVFvO
给定一个抽象模板类Runnable
和一个从Runnable<int>
继承的实现Derived
:
#include <iostream>
#include <memory>
using namespace std;
template<class... Args>
struct Runnable
{
virtual ~Runnable() = default;
virtual void f(Args... args) const = 0;
};
struct Derived : public Runnable<int>
{
void f(int x) const override
{
cout << "f(" << x << ")" << endl;
}
};
给定指向派生类型的智能指针,函数accept_variadic
的模板参数推导失败的根本原因是什么?
template<class... Args>
void accept_variadic(std::unique_ptr<Runnable<Args...>> o, Args&&... args)
{
o->f(forward<Args>(args)...);
}
int main()
{
accept_variadic(make_unique<Derived>(), 5); // Error (no conversion)
return 0;
}
但是直接给定一个没有智能指针的引用(或指针(工作:
template<class... Args>
void accept_variadic_ref(const Runnable<Args...>& o, Args&&... args)
{
o.f(forward<Args>(args)...);
}
int main()
{
accept_variadic_ref(Derived(), 5); // OK
return 0;
}
另外,有没有办法支持模板类推导指南或使用不同的智能指针的类似用法(在我的应用程序中拥有原始指针和非生存期扩展引用会很困难(。
而不是:
template<class... Args>
void accept_variadic(std::unique_ptr<Runnable<Args...>> o, Args&&... args)
{
o->f(forward<Args>(args)...);
}
您可以使用 TMP 来获取您想要的内容:
template<class T, class... Args>
std::enable_if_t<std::is_convertible_v<std::unique_ptr<T>,
std::unique_ptr<Runnable<Args...>>>>
accept_variadic(std::unique_ptr<T> o, Args&&... args)
{
o->f(forward<Args>(args)...);
}
(在此处查看完整代码(
这不是 100% 等效的,因为建议的解决方案接受派生类型的std::unique_ptr
,而原始代码将仅接受基类型。
原始代码不起作用,因为模板会匹配需要转换的类型。在代码中,两种std::unique_ptr
类型不是彼此的基础/派生类型,因此模板不匹配。
使用提出的解决方案,函数接受原始std::unique_ptr
,前提是它可以转换为函数内部的基类型。std::enable_if_t
确保其他类型不匹配,只有可以转换为基的类型不匹配。
编辑
在问题的某些变体中,原始解决方案可能存在问题。这可能发生在在基类上调用f()
与在派生类上调用f()
不同的问题变体中。发生这种情况有几种可能性(但不是在原始问题中(。为了克服这种风险,应将accept_variadic()
更改为:
template<class T, class... Args>
std::enable_if_t<std::is_convertible_v<T&, Runnable<Args...>&>>
accept_variadic(std::unique_ptr<T> o, Args&&... args)
{
// could also be solved with
// std::unique_ptr<Runnable<Args...>> base = std::move(o);
Runnable<Args...> & runnable = *o;
runnable.f(forward<Args>(args)...);
}
相关文章:
- 1d 智能指针不适用于语法 (*)++
- 如何反转整数参数包
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 如何使用默认参数等选择模板专业化
- 通过智能指针和转换对基本模板参数进行模板推导
- 将派生类作为参数传递给方法,该方法是具有智能指针的基类
- 是否可以创建一个指向对象的智能指针并将此智能指针作为参数传递给构造函数?
- 如何制作智能指针的可变参数函数?
- 将变量传递给将智能指针作为参数的函数,而没有该变量是智能指针本身
- 我可以省略头文件中智能指针的类型参数吗?
- 函数参数中的Qt智能指针
- 智能感知:类型 "HWND" 的参数与类型 "rawData::HWND" 的参数不兼容
- 智能指针和参数列表分配规则
- 将智能指针传递给引用指针参数的函数
- 如何使用COM智能指针作为内外参数来调用例如库函数
- 智能感知:没有构造函数"Sock::Connection::Connection"实例与参数列表C++匹配
- 智能感知:类型 "const char *" 的参数与类型 "LPCWSTR" 的参数不兼容
- Visual Studio 2010 - C++智能感知不起作用(甚至不是Ctrl + Space),没有函数名称,没有参数列表,什么都没有
- 2 智能感知:类型 "const char *" 的参数与类型 "LPCWSTR" 的参数不兼容
- 如何智能地将多个参数写入hdf5文件