jjzjj

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

coder 2024-02-05 原文

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

#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/

有关c++ - 重载解析和指向 const 的共享指针的更多相关文章

  1. Ruby 解析字符串 - 2

    我有一个字符串input="maybe(thisis|thatwas)some((nice|ugly)(day|night)|(strange(weather|time)))"Ruby中解析该字符串的最佳方法是什么?我的意思是脚本应该能够像这样构建句子:maybethisissomeuglynightmaybethatwassomenicenightmaybethiswassomestrangetime等等,你明白了......我应该一个字符一个字符地读取字符串并构建一个带有堆栈的状态机来存储括号值以供以后计算,还是有更好的方法?也许为此目的准备了一个开箱即用的库?

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby - 用逗号、双引号和编码解析 csv - 2

    我正在使用ruby​​1.9解析以下带有MacRoman字符的csv文件#encoding:ISO-8859-1#csv_parse.csvName,main-dialogue"Marceu","Giveittohimóhe,hiswife."我做了以下解析。require'csv'input_string=File.read("../csv_parse.rb").force_encoding("ISO-8859-1").encode("UTF-8")#=>"Name,main-dialogue\r\n\"Marceu\",\"Giveittohim\x97he,hiswife.\"\

  4. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  5. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  6. ruby-on-rails - 我更新了 ruby​​ gems,现在到处都收到解析树错误和弃用警告! - 2

    简而言之错误:NOTE:Gem::SourceIndex#add_specisdeprecated,useSpecification.add_spec.Itwillberemovedonorafter2011-11-01.Gem::SourceIndex#add_speccalledfrom/opt/local/lib/ruby/site_ruby/1.8/rubygems/source_index.rb:91./opt/local/lib/ruby/gems/1.8/gems/rails-2.3.8/lib/rails/gem_dependency.rb:275:in`==':und

  7. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  8. ruby - 用 YAML.load 解析 json 安全吗? - 2

    我正在使用ruby2.1.0我有一个json文件。例如:test.json{"item":[{"apple":1},{"banana":2}]}用YAML.load加载这个文件安全吗?YAML.load(File.read('test.json'))我正在尝试加载一个json或yaml格式的文件。 最佳答案 YAML可以加载JSONYAML.load('{"something":"test","other":4}')=>{"something"=>"test","other"=>4}JSON将无法加载YAML。JSON.load("

  9. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  10. ruby - 如何使用 Nokogiri 解析纯 HTML 表格? - 2

    我想用Nokogiri解析HTML页面。页面的一部分有一个表,它没有使用任何特定的ID。是否可以提取如下内容:Today,3,455,34Today,1,1300,3664Today,10,100000,3444,Yesterday,3454,5656,3Yesterday,3545,1000,10Yesterday,3411,36223,15来自这个HTML:TodayYesterdayQntySizeLengthLengthSizeQnty345534345456563113003664354510001010100000344434113622315

随机推荐