提问者:小点点

C 20概念需要运算符重载结合用户自定义模板运算符重载功能


考虑以下概念,其中需要范围Rvalue_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; };

它可以很好地与std::向量

static_assert(printable_range<std::vector<int>>);

但是如果我定义一个模板运算符

std::ostream& operator<<(std::ostream& os, const auto& x) { return os << x; }

GCC和MSVC可以传递以下断言,但Clang失败:

static_assert(printable_range<std::vector<std::vector<int>>>);

我应该信任哪个编译器?它看起来像一个Clangbug。

奇怪的是,如果我用运算符定义一个自定义structS

struct S{};
std::ostream& operator<<(std::ostream& os, const S&) { return os; }

同样的断言在MSVC中失败,但GCC仍然接受它:

static_assert(printable_range<std::vector<std::vector<int>>>);

是MSVCbug吗?

如果我转换运算符

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!

共2个答案

匿名用户

我应该信任哪个编译器?它看起来像一个Clangbug。

这是一个GCC/MSVCbug。os的名称查找

GCC和MSVC这样做的事实是bug。

GCC的问题是,它使用运算符进行查找,具体来说,只是找到了比它应该找到的更多的东西(参见51577,感谢T. C.)。这就是为什么它可以找到运算符

真的,这些是同一个示例,只是名称不同(printvs运算符

匿名用户

Clang是正确的。这是通常的两阶段查找规则,已知GCC对运算符的处理不正确(MSVC也不完全以正确的两阶段查找支持而闻名,尽管它们正在变得更好)。

运算符的普通不合格查找

相关问题