Я написал код, который определяет, может ли один объект быть передан в std::ostream
.Однако, хотя он работает в Clang, он не работает в GCC.После упрощения кода возникает проблема, когда два класса имеют оператор <<, определенный в разных пространствах имен. </p>
Ниже приведен (упрощенный) код (и здесь он находится на Godbolt):
#include <iostream>
namespace test_ns {
// Define two (trivial) classes.
class Class1 { };
class Class2 { };
// First class has ostream operator defined in namespace test_ns
std::ostream & operator<<(std::ostream & out, const Class1 & v) {
return out << "Class1 Output!";
}
}
// Second class as ostream operator defined in global namespace.
std::ostream & operator<<(std::ostream & out, const test_ns::Class2 & v) {
return out << "Class2 Output!";
}
namespace test_ns {
// Simple template that always evaluates to bool (for SFINAE-based reflection)
template <typename EVAL_TYPE> using bool_decoy = bool;
// Two version of HasPrint that test the operator<< into ostream.
// First version preferred if << works...
template <typename T>
bool HasPrint(bool_decoy<decltype( std::declval<std::ostream&>() << std::declval<T>() )>) {
return true;
}
// Second version as a fallback.
template <typename T>
bool HasPrint(...) {
return false;
}
}
int main()
{
std::cout << test_ns::HasPrint<test_ns::Class2>(true) << std::endl;
}
Вот ошибка, которую я получаю в gcc 9.1:
<source>: In instantiation of 'bool test_ns::HasPrint(test_ns::bool_decoy<decltype ((declval<std::basic_ostream<char, std::char_traits<char> >&>() << declval<T>()))>) [with T = test_ns::Class2; test_ns::bool_decoy<decltype ((declval<std::basic_ostream<char, std::char_traits<char> >&>() << declval<T>()))> = <type error>]':
<source>:40:55: required from here
<source>:26:68: error: no match for 'operator<<' (operand types are 'std::basic_ostream<char>' and 'test_ns::Class2')
26 | bool HasPrint(bool_decoy<decltype( std::declval<std::ostream&>() << std::declval<T>() )>) {
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
(сопровождается длинным списком кандидатов)
Пока я могу (и буду)рефакторинг кода, чтобы обойти эту проблему, я не до конца понимаю, что здесь происходит не так.Я неправильно определяю операторы, или это проблема с gcc?