【问题标题】:Why is there no deduction guide for string_view?为什么没有string_view的演绎指南?
【发布时间】:2019-11-25 12:12:51
【问题描述】:

在查看basic_string_view 的引用时,似乎缺少从std::basic_string 构造的(显式)推导指南——巧合与否,似乎为指针类型生成了隐式推导指南(@ 987654325@和const wchar_t*)

目前我在模板中采用以下 trick,该模板应该只接受任何可以卡在 string view 上的东西:

using CharIn = decltype(std::basic_string(str_in))::value_type;//basicly: char or wchar_t

std::basic_string_view<CharIn> str = str_in;

我宁愿只写:

std::basic_string_view str = str_in;//<--using deduction guide (currently does not work for basic_string)

我想知道这是否被考虑过?

【问题讨论】:

  • 这可能是相对安全的:右值basic_strings 绑定到const basic_string &amp; 并创建一个悬空视图。 (原始)字符串文字不会悬空。
  • @Caleth 如果我正确理解你的论点,它就站不住脚:foonathan.net/2017/03/string_view-temporary
  • @rustyx 是的,你可以毫不费力地从string 构造一个string_view。我猜只是模板案例似乎缺少演绎指南?
  • 这里的问题和template &lt;CharT&gt; void foo(std::basic_string_view&lt;CharT&gt;)类似,CharT没有推导出来
  • “巧合的是,似乎生成了隐式演绎指南..”——这并非巧合。

标签: c++ language-lawyer c++17 template-meta-programming string-view


【解决方案1】:

一般来说,您尝试的那种双重隐式转换是一个非常糟糕的主意,C++ 标准会尽其所能阻止您尝试执行它们。例如,重载解析不允许它;如果转换序列会尝试进行双重转换,它就会完全停止考虑该重载。

让我们考虑一下您的推导指南的意图:允许 std::basic_string_view str = str_in; 适用于任何类型的 T,它可以隐式转换,而不是某种类型的 basic_string_view,而是 basic_string

好的,那么...std::basic_string_view str = str_in; 实际上是做什么的?好吧,它必须将任何str_in 转换为某种basic_string。所以str_in 是可以调用basic_string 的单参数构造函数的类型,或者str_in 是具有重载operator basic_string&lt;...&gt; 的类型。

让我们考虑basic_string 的单参数构造函数。其中包括:一个仅用于创建空字符串的分配器、一个复制构造函数、一个移动构造函数、一个初始化列表构造函数,以及一个采用const charT* 的构造函数。只有后一种对这种情况有用,所以str_in 必须是某种charT* 类型。好吧,basic_string_viewimplicit 推导指南已经可以很好地处理这个问题。所以不需要双重转换。

所以我们现在只讨论str_in 是具有转换运算符的类型的情况。好的:这个转换运算符是否将 reference 返回到 basic_string 类型?

因为如果没有,那么std::basic_string_view str = str_in; 将产生一个悬空引用。将创建一个临时的basic_string,其内容将被视图引用。然后临时的被破坏了,我们的观点立即变得毫无价值。

这样的事情就是 C++ 不喜欢双重隐式转换的原因。如果你必须输入这个:std::basic_string_view str = basic_string(str_in);,那么每个人都会清楚你的代码为什么会被破坏:你正在存储一个临时视图。

如果str_in 本身就是一个字符串类型,那么最好只给它一个operator basic_string_view 重载。

【讨论】:

  • 你是在争论推导是一种转换吗?因为您已经可以将 std::string 分配给 std::string_view,即。带有显式模板参数,所以它只是没有发生的推论。
  • @darune:我认为使用该演绎指南的唯一方法是通过调用需要双重转换的构造函数的动作。所以真的没有区别。由于string 中的转换运算符,std::string 转换为string_view,而不是string_view 中的构造函数。也就是说,提供到视图的转换是字符串类型的责任,而不是相反。
  • 嗯,我明白了,这实际上让我有点惊讶 - 为什么他们选择那个设计而不是另一个,但有点令人费解。通常,转换运算符最适合用于最简单的情况(甚至无法使用其他选项),并且在设计方面不能很好地“缩放”。
  • @darune: string_view 应该是通用语类型。您将string_view 放入您的界面,该界面现在支持任何可转换为string_view 的字符串类型。由于string_view 是标准定义的类型,因此用户定义的字符串类型可转换为string_view 的唯一方法是为每个字符串类型提供一个转换运算符到string_view。这意味着每个字符串类型都应该“说话”string_view;不是string_view 会因每种字符串类型而改变。
猜你喜欢
  • 2023-03-28
  • 1970-01-01
  • 2021-07-05
  • 2019-09-23
  • 2021-06-20
  • 2019-09-11
  • 2019-11-04
  • 2021-11-19
  • 2020-05-09
相关资源
最近更新 更多