给出以下代码:
#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);
}
在行#1
中,编译错误是因为jostream
有一个名为operator<<
的函数成员,因此调用行#1
(内部的注释行) jostream::operator<<
,而不是代码的第一行)尝试使用两个不存在的参数对jostream::operator<<
进行显式调用。
是否有任何强制调用具有冲突名称的非成员函数的技巧? (除了调用进行实际调用的外部函数)。 ::operator<<
调用显然不是解决方案,因为重载可能位于用户命名空间内,如示例所示。
(使用gcc-7.2.0)
答案 0 :(得分:3)
using std::operator<<;
operator<<(*this, v);
无论如何, std
是*this
的关联命名空间,因此这不会在重载集中引入任何新内容。或者,定义一个名称空间范围operator<<
,使用一些虚拟类型并将其与using
结合使用。