gpt4 book ai didi

使用 shared_ptr 到 const T 的 C++ 模板实例化

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:32:09 26 4
gpt4 key购买 nike

假设我有一个类

template <typename T>
class A {
public:
template <typename V>
void f(std::tr1::shared_ptr<const std::vector<V> > v1,
std::tr1::shared_ptr<const std::vector<float> > v2) {}
};

以下不编译:

 A<string> a;
std::tr1::shared_ptr<std::vector<float> > v1(new std::vector<float>());
std::tr1::shared_ptr<std::vector<float> > v2(new std::vector<float>());
a.f(v1, v2);

编译错误是:

error: no matching function for call to 'A<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::f(std::tr1::shared_ptr<std::vector<float, std::allocator<float> > >&, std::tr1::shared_ptr<std::vector<float, std::allocator<float> > >&)'

编译器无法生成 std::tr1::shared_ptr<std::vector<float> >进入 std::tr1::shared_ptr<const std::vector<float> >对于第一个参数。然而它可以用于第二个(非模板参数)。

一个解决方案是更改对 f() 的调用,这样调用它 f<float>(...) .
另一种解决方案是将 v1 声明为 const vector<float>. 的 shared_ptr

  1. 为什么模板实例化在这里表现如此不同?
  2. 我对 shared_ptr<const T> 的理解作为方法的参数是该方法不能更改 shared_ptr 的内容指向。如果我们改变 shared_ptr s 到原始指针和 v1 , v2作为指向 vectors 的原始指针,那么代码将编译正常。关于什么 shared_ptr这会破坏模板推导吗?

最佳答案

相关类型?

如您所知,T*const T*是相关类型。从第一个到第二个有一个标准转换(资格转换)。

首先,你必须意识到 A<T>A<const T>不是一般的相关类型。这些类型可以有不同的大小、表示和用途。可以定义一个,但不能定义另一个。

特别是,A<const T>不是 const 限定 A<T> ,所以两者之间没有限定转换,C++ 不够灵活,无法声明用户定义的限定转换。 (用户不能声明任何标准转换,只能声明用户定义的转换 - 用户定义的转换不是标准转换。)

因此,用户定义类型与基本类型根本不同:它们不能像基本类型那样相关。

shared_ptr<>

shared_ptr<>旨在形成一系列兼容类型:shared_ptr<T>可隐式转换为 shared_ptr<U>比较 T*可隐式转换为 U* .特别是,shared_ptr<T>可隐式转换为 shared_ptr<const T> .它也可以隐式转换为 shared_ptr<void> , 所以同理。

因为类型 shared_ptr<const T>shared_ptr<T>没有任何特殊方式相关,从 shared_ptr<T> 的转换至 shared_ptr<const T>shared_ptr<T>没有区别至 shared_ptr<void> .这只是两种不同的转换,但在任何情况下都不能被视为“首选”,这与 T* 的转换不同。至 const T* (排名 = 完全匹配)优于从 T* 的转换至 void* (排名 = 转化)。

函数模板

在推导的模板函数参数上允许一些标准转换:

  • 资格转换
  • 一些指针转换:派生到基数
  • ...

但正如我们所见,shared_ptr<> 之间不存在此类转换类型。

这意味着即使允许编译器为模板参数枚举所有可能的类型来转换函数模板

template <typename V>
void f (shared_ptr<const T> v1);

进入无限的函数原型(prototype)集:

for every type T,
such that shared_ptr<const T> can be instantiated:
f (shared_ptr<const T>)

除非你有完全匹配,否则你将无法调用函数:给定声明

struct Base {};
struct Derived : Base {};

shared_ptr<Derived> d;

f的集合中原型(prototype),有:

f (shared_ptr<const Base>)
f (shared_ptr<const Derived>)

因此请调用 f (d)将是模棱两可的,因为这两个候选者都涉及不同的用户定义的转换。

关于使用 shared_ptr 到 const T 的 C++ 模板实例化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5600150/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com