gpt4 book ai didi

c++ - 重载解析和指向 const 的共享指针

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:45:09 27 4
gpt4 key购买 nike

我正在将大型代码转换为使用自定义共享指针而不是原始指针。我在重载解析方面有问题。考虑这个例子:

#include <iostream>

struct A {};

struct B : public A {};

void f(const A*)
{
std::cout << "const version\n";
}

void f(A*)
{
std::cout << "non-const version\n";
}

int main(int, char**)
{
B* b;
f(b);
}

此代码正确写入“非常量版本”,因为 qualification conversions在隐式转换序列的排名中发挥作用。现在看一下使用 shared_ptr 的版本:

#include <iostream>
#include<memory>

struct A {};

struct B : public A {};

void f(std::shared_ptr<const A>)
{
std::cout << "const version\n";
}

void f(std::shared_ptr<A>)
{
std::cout << "non-const version\n";
}

int main(int, char**)
{
std::shared_ptr<B> b;
f(b);
}

此代码无法编译,因为函数调用不明确。

我明白 user-defined deduction-guide将是一个解决方案,但它在 Visual Studio 中仍然不存在。

我正在使用正则表达式转换代码,因为有数以千计的此类调用。正则表达式无法区分匹配 const 版本的调用和匹配非 const 版本的调用。使用共享指针时是否可以更好地控制重载决议,并避免手动更改每个调用?当然,我可以 .get() 原始指针并在调用中使用它,但我想完全消除原始指针。

最佳答案

你可以引入额外的重载来为你做延迟:

template <class T>
void f(std::shared_ptr<T> a)
{
f(std::static_pointer_cast<A>(a));
}

template <class T>
void f(std::shared_ptr<const T> a)
{
f(std::static_pointer_cast<const A>(a));
}

您还可以使用 std::enable_if将第一个过载限制为非 const T s,和/或将两个重载限制为 T s 派生自 A .

这是如何工作的:

你有一个 std::shared_ptr<X>对于一些 X这既不是 A也不const A (它是 Bconst B )。如果没有我的模板重载,编译器必须选择转换这个 std::shared_ptr<X>std::shared_ptr<A>std::shared_ptr<const A> .两者都是同样好的排名转换(都是用户定义的转换),因此存在歧义。

添加模板重载后,有四种参数类型可供选择(让我们分析X = const B案例):

  1. std::shared_ptr<A>
  2. std::shared_ptr<const A>
  3. std::shared_ptr<const B>从第一个模板实例化,带有 T = const B .
  4. std::shared_ptr<const B>从第二个模板实例化,带有 T = B .

显然类型 3 和类型 4 优于类型 1 和 2,因为它们根本不需要转换。因此,将选择其中之一。

类型 3 和类型 4 本身是相同的,但是通过模板的重载解析,会引入额外的规则。即,“更专业”的模板(更多的非模板签名匹配)优于一个更少的模板专门。因为重载 4 有 const在签名的非模板部分(T 之外),它更专业,因此被选中。

没有规则说“模板更好”。事实上,恰恰相反:当模板和非模板的成本相同时,非模板优先。这里的技巧是模板的成本(不需要转换)比非模板(需要用户定义的转换)更少

关于c++ - 重载解析和指向 const 的共享指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41040355/

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