I have written code that detects if one object can be streamed into an std::ostream
. However, while it works in clang, it fails in gcc. After simplifying the code, the problem seems to occur when two classes have operator<< defined in different namespaces.
Below is the (simplified) code (and here it is on 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;
}
Here is the error I receive in 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>() )>) {
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
(followed by a long list of candidates)
While I can (and will) refactor the code to circumvent this issue, I don't fully understand what is going wrong here. Am I improperly defining the operators, or is this a problem with gcc?
Aucun commentaire:
Enregistrer un commentaire