[英]C++20 concepts require operator overloading combine with user-define template operator overloading function
Consider the following concept
which requires
the value_type
of a range
R
is printable:考虑以下
concept
,它requires
R
range
的value_type
是可打印的:
#include <iostream>
#include <iterator>
template <class R, typename T = std::ranges::range_value_t<R>>
concept printable_range = requires(std::ostream& os, const T& x) { os << x; };
It works fine with std::vector<int>
on different three compliers:它适用于不同的三个编译器上的
std::vector<int>
:
static_assert(printable_range<std::vector<int>>);
but if I define a template operator<<
function with any type x
after concepts
define:但是,如果我在
concepts
定义后定义了具有任何类型x
的模板operator<<
function:
std::ostream& operator<<(std::ostream& os, const auto& x) { return os << x; }
GCC and MSVC can pass the following assert but Clang fails : GCC 和 MSVC 可以通过以下断言,但 Clang失败:
static_assert(printable_range<std::vector<std::vector<int>>>);
Which compiler should I trust?我应该信任哪个编译器? It seems like a Clang bug.
这似乎是一个 Clang 错误。
Weirdly, If I define a custom struct S
with operator<<
support before the concept
printable_range
define:奇怪的是,如果我在定义
printable_range
concept
之前定义了一个带有operator<<
支持的自定义结构S
:
struct S{};
std::ostream& operator<<(std::ostream& os, const S&) { return os; }
Same assert fails with MSVC, but GCC still accept it: MSVC 的相同断言失败,但 GCC 仍然接受它:
static_assert(printable_range<std::vector<std::vector<int>>>);
Is it an MSVC bug?它是一个 MSVC 错误吗?
If I transform the operator<<
function into a named function print
, then all the compiler fails on the second assert.如果我将
operator<<
function 转换为名为 function print
,那么所有编译器都会在第二个断言上失败。 This surprised me since it looks equivalent to case 1, the key points here are the member function vs. free function or operator overloading function vs. free function ? This surprised me since it looks equivalent to case 1, the key points here are the member function vs. free function or operator overloading function vs. free function ?
void print(int x) { std::cout << x; };
template <class R, typename T = std::ranges::range_value_t<R>>
concept printable_range = requires(const T& x) { print(x); };
void print(auto x) { std::cout << x; };
static_assert(printable_range<std::vector<int>>);
static_assert(printable_range<std::vector<std::vector<int>>>); // failed!
Which compiler should I trust?
我应该信任哪个编译器? It seems like a Clang bug.
这似乎是一个 Clang 错误。
This is a GCC/MSVC bug.这是一个 GCC/MSVC 错误。 Name lookup for
os << x
will perform argument-dependent lookup to find any other associated operator<<
s, but the associated namespaces here are just std
. os << x
的名称查找将执行与参数相关的查找以查找任何其他关联的operator<<
s,但此处关联的命名空间只是std
。 Your operator<<
is not in namespace std
, so lookup should not find it, so there should be no viable candidates.您的
operator<<
不在namespace std
中,因此查找不应该找到它,所以应该没有可行的候选人。
The fact that GCC and MSVC do so is a bug. GCC 和 MSVC 这样做的事实是一个错误。
The issue with GCC is that its lookup with operators, specifically, just finds more things than it should (see 51577 , thanks T.C.). GCC 的问题在于它与操作员的查找,具体来说,只是找到了比它应该的更多的东西(参见51577 ,感谢 T.C。)。 That's why it can find the
operator<<
but not the print
.这就是为什么它可以找到
operator<<
而不是print
的原因。
Really, these are the same example, just with a different name ( print
vs operator<<
) and they should have the same behavior.确实,这些是同一个示例,只是名称不同(
print
vs operator<<
),它们应该具有相同的行为。
Clang is correct. Clang 是正确的。 This is the usual two-phase lookup rule that GCC is known to handle incorrectly for operators (and MSVC is also not exactly known for proper two-phase lookup support, though they are getting better).
这是通常的两阶段查找规则,已知 GCC 对操作员的处理不正确(MSVC 也不完全以正确的两阶段查找支持而闻名,尽管它们正在变得更好)。
Ordinary unqualified lookup for operator<<
only occurs from the definition context and finds nothing.对
operator<<
的普通非限定查找只发生在定义上下文中,什么也找不到。 Argument-dependent lookup can't find the operator<<
in the global namespace either, since the global namespace is not an associated namespace of std::vector<int>
.依赖于参数的查找也无法在全局命名空间中找到
operator<<
,因为全局命名空间不是std::vector<int>
的关联命名空间。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.