gol*_*ver 5 c++ string-view c++17
我看到string_view和string都有对称运算符==,对于字符串,它有构造函数接受string_view和运算符将自身转换为string_view.所以当我们尝试在string_view和string之间使用operator == compare时,它应该是不明确的吗?
我认为我的想法一定有问题.请提前告知我,谢谢!
例:
std::string s1 = "123";
std::string_view s2 = "123";
// in the following comparison, will s1 use the convert operator to generate a string_view, or will s2 use string's string_view constructor to generate a string?
if (s1 == s2) {...}
Run Code Online (Sandbox Code Playgroud)
这样的比较不能模棱两可的原因是,普通类型std::string也不std::string_view是。而是这些是类模板实例化,相应的比较运算符也是如此:
template <class charT, class traits, class alloc>
constexpr bool operator==(const basic_string<charT, traits, alloc>& lhs,
const basic_string<charT, traits, alloc>& rhs) noexcept;
template <class charT, class traits>
constexpr bool operator==(basic_string_view<charT, traits> lhs,
basic_string_view<charT, traits> rhs) noexcept;
Run Code Online (Sandbox Code Playgroud)
这样定义的功能模板不考虑任何转换。相反,他们期望操作数具有完全相同的类型,因为只有这样推论才能成功(可以为左右操作数的模板参数推导相同的类型),从而产生可行的候选对象。类似地:
template <typename T>
void foo(T, T);
foo(42, 'x'); // error
Run Code Online (Sandbox Code Playgroud)
由于参数类型不匹配而失败,T不能为int或char,尽管两者之间存在转换。也:
struct my_string
{
operator std::string() const { return ""; }
};
std::string s;
my_string ms;
s == ms; // error
Run Code Online (Sandbox Code Playgroud)
失败,因为编译器无法basic_string<charT, traits, alloc>从推导my_string,尽管确实存在对其实例化的隐式转换。
s1 == s2但是,该比较确实有效,因为标准库的实现预计会提供重载,可以考虑从任何类型到std::basic_string_view的隐式转换(这样的隐式转换存在从std::string到std::string_view)。例如,可以通过禁止参数之一的推导来实现,如[string.view.comparison] / p1的示例部分所示:
template <class charT, class traits>
constexpr bool operator==(basic_string_view<charT, traits> lhs,
__identity<basic_string_view<charT, traits>> rhs) noexcept;
Run Code Online (Sandbox Code Playgroud)
通过将其中一个操作数的类型__identity定义为template <class T> using __identity = decay_t<T>;,它引入了非推导上下文,从而为std::basic_string_view隐式转换为std::basic_string_view类模板的相同实例的某些参数和另一个参数创建了重载。
这是因为[string.view.comparisons] 中有一个奇怪的子句:
让
S是basic_string_view<charT, traits>,和sv是一个实例S。实现应提供足够的附加重载标记constexpr,noexcept以便可以根据表 62 比较t具有隐式转换的对象S。
表 62 列出了所有比较运算符,以及表达式两侧的视图。
由于std::string具有到 的隐式转换std::string_view,因此将选择此重载。此类重载将与s1 == s2大小写完全匹配,因此不会考虑隐式转换。
基本上,这是通过 SFINAE 工具实现的。像这样的东西:
template<typename Str>
std::enable_if_t<std::is_convertible_v<std::string_view, Str>, bool> operator==(const Str &rhs, const std::string_view &lhs);
Run Code Online (Sandbox Code Playgroud)
这种重载不需要隐式转换,所以它比任何需要的重载都要好。
| 归档时间: |
|
| 查看次数: |
1743 次 |
| 最近记录: |