I saw this example of using SFINAE to check if a type is streamable here. However, I noticed that it is not portable, i.e. returns different results for templated types with different compilers. I'd be glad for any tips to understand the problem here.
The code below returns true, false
with any version of clang++ and GCC 12 or higher, but true, true
with earlier versions of GCC.
You can try it online here.
#include <iostream>
#include <type_traits>
#include <vector>
template <typename T, typename dummy = void>
struct is_printable : std::false_type {};
template <typename T>
struct is_printable<
T, typename std::enable_if_t<std::is_same_v<
std::remove_reference_t<decltype(std::cout << std::declval<T>())>,
std::ostream>>> : std::true_type {};
template <typename T>
inline constexpr bool is_printable_v = is_printable<T>::value;
struct C {};
std::ostream& operator<<(std::ostream& os, const C& c) {
os << "C";
return os;
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& v) {
for (const auto& el : v) {
os << el;
}
return os;
}
int main(int argc, const char* argv[]) {
std::cout << std::boolalpha;
std::cout << is_printable_v<C> << std::endl;
std::cout << is_printable_v<std::vector<int>> << std::endl;
return 0;
}
std::ostream& operator<<
is before thestruct is_printable
both version are "true true" – Lurlene