我想检测一个给定类型的插入运算符。通常我会检查一个带有正确签名的重载函数。假设我有一个A类,那么
template<typename T>
struct insert_operator_type
{
using type = typename std::ostream&(*)(std::ostream&, const T&);
};
...
std::is_same<
decltype(static_cast<typename insert_operator_type<A>::type> (&operator<<)),
std::ostream&(*)(std::ostream&, A const&)
>::value
会告诉我他们是一样的,我可以推断出运营商的存在。使用运算符&lt;&lt;但是类型B可能会解析为类型A.说出类似
的内容template<typename T>
class A
{
public:
T* type1 = nullptr;
};
typedef A<int> BImpl;
class B : public BImpl
{
public:
B() {}
};
template<typename T>
std::ostream& operator<<(std::ostream& os, const A<T>& a)
{
os << "printing A<T>" << std::endl;
return os;
}
现在我可以
B b;
std::cout << b << std::endl;
但是没有
std::ostream&(*)(std::ostream&, B const&)
相反,编译器计算出使用BImpl版本并且习惯用法无法识别B的插入运算符。
我是否可以确定存在重载函数,以便不能为特定类型指定函数,但对于某些类型,给定类型将转换为?
答案 0 :(得分:4)
您可能只想使用SFINAE来检查插入的整个表达式是否有效。
// std::void_t in C++1z
template <class...>
using void_t = void;
template <class, class = void_t<>>
struct can_be_ostreamed : std::false_type { };
template <class T>
struct can_be_ostreamed<T, void_t<
decltype(std::declval<std::ostream&>() << std::declval<T>())
>> : std::true_type { };