Вызов перегрузок операторов, не являющихся членами

Учитывая следующий код:

#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)

4

Решение

using std::operator<<;
operator<<(*this, v);

std это связанное пространство имен *this во всяком случае, так что это не вносит ничего нового в набор перегрузки. В качестве альтернативы, определите область имен operator<< принимая какой-то фиктивный тип и потяните это с using,

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]