我试图了解在 Clang 或 MSVC 标准库实现的以下示例中如何考虑
operator==
进行重载解析。
#include <string>
#include <string_view>
//#define WORKAROUND 1
namespace tst
{
template<class T>
class string_view
{
#if WORKAROUND
friend bool operator==( string_view a, string_view b);
#endif
};
template<class T, class A>
class string
{
public:
operator string_view<T>() const;
};
#if !WORKAROUND
template<class T>
bool operator==( string_view<T> a, string_view<T> b);
#endif
}
void foo()
{
tst::string<char, int> s1;
tst::string_view<char> sv;
if (s1 == sv) {}
if (sv == s1) {}
}
int main()
{
std::string s1;
std::string_view sv;
if (s1 == sv) {}
if (sv == s1) {}
return 0;
}
它在定义
WORKAROUND
时编译,因为它在 here 中有很好的描述。但是,在查看 Clang 和 MSVC 的来源时,我没有发现该库使用了此解决方法。该运算符在类外部定义如下:
template<class _CharT, class _Traits>
_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
bool operator==(basic_string_view<_CharT, _Traits> __lhs,
basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT
{
if (__lhs.size() != __rhs.size()) return false;
return __lhs.compare(__rhs) == 0;
}
参见github。
所以我的问题是 STL 是如何工作的?
std::string
有一个运算符转换函数可以做到这一点您是否注意到类
std::string_view
没有从 std::string
转换而来的构造函数?
相反,它依赖于类
std::string
中的运算符转换函数。
更准确地说,它依赖于
std::basic_string<CharT,Traits,Allocator>::operator basic_string_view
。 请参阅 Cpp 参考。
当您从
std::string_view
构造 std::string
对象时,您将调用从 string
到 string_view
的隐式转换(这会创建一个临时对象),然后调用 std::string_view
的复制构造函数。
虽然我还没有研究过 Clang 或 MSVC 库
std::basic_string_view
,但我相信类似的事情正在发生。使用 string
类中的运算符转换函数将 string_view
隐式转换为 string
。之后,您可以对两个 string_view
对象进行简单比较。