C++ 调用非成员运算符重载
给定以下代码:C++ 调用非成员运算符重载,c++,overloading,c++17,name-collision,C++,Overloading,C++17,Name Collision,给定以下代码: #include <iostream> #include <functional> #include <utility> template<class O, class T, class = void> constexpr bool ostreamable_with = false; template<class O, class T> // If there's user-defined overloads con
#include <iostream>
#include <functional>
#include <utility>
template<class O, class T, class = void>
constexpr bool ostreamable_with = false;
template<class O, class T> // If there's user-defined overloads
constexpr bool ostreamable_with<
O, T, std::void_t<decltype(operator<<(std::declval<O>(),
std::declval<T>()))>> = true;
struct jostream : std::reference_wrapper<std::ostream>
{
using reference_wrapper::reference_wrapper;
std::ostream& os() { return *this; }
template<class T>
jostream& operator<<(T const& v)
{
if constexpr(ostreamable_with<jostream&, T const&>)
// This enables user-defined conversion on `v` too
operator<<(*this, v); // #1
else
os() << v;
return *this;
}
};
namespace user {
struct C
{ int a; };
inline jostream& operator<<(jostream& os, C const& c)
{ return os << c.a; }
}
int main()
{
jostream jos(std::cout);
user::C u{1};
jos << std::cref(u);
}
#包括
#包括
#包括
模板
constexpr bool ostreamable_,带=false;
模板//如果存在用户定义的重载
constexpr bool ostremable_与<
O、 T,std::void_T使用std::operatorLine#1是#include
@mnistic哈哈,在jostream::operatorCan'T内有一条带有行号的注释,@Stargateur您需要激活-std=c++17
,但clang不完全支持。在这里测试:@Peregring lk well c++17不是官方的,我使用c++1z和叮当声。另外,我的gcc不像你的那样编译。在你的问题中输入你使用的编译器版本是有用的,因为你使用了不稳定的特性。:o但是std::operator@Peregring-lk我也在想这件事。显然,运算符的虚拟重载(声明)是。。。(子)命名空间<代码> STD<代码>,不合格查找也会考虑并行代码(子)命名空间,如<代码>用户< /代码>,因为这也可以从<代码>::(即,从代码级别> JoSoos声明)访问。但我不能说。。。T.C.?@dfri我认为问题是,一旦你用一个非成员函数污染了查找空间,ADL(如果一个成员函数出现在正常的非限定查找中,它最初不会被考虑)就会被激活,并且通过参数发现用户定义的重载。我认为T.C.技巧是使用std
名称空间激活ADL查找,因为在正常的“ADL模式”中,std
名称空间已经被考虑,因为jostream
继承自std::reference\u wrapper
。因此,using std::operator我想知道的是管理“ADL激活”的规则,并完全理解重载集是什么,使用和不使用该声明。
using std::operator<<;
operator<<(*this, v);