C ++检测是否存在按名称接受特定类型的函数

C++ Detect if there exists a function by name that accepts a particular type

我想检测给定类型是否有插入运算符。通常我会检查是否存在具有正确签名的重载函数。假设我有一个 class 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 

会告诉我它们是一样的,我可以推断出运算符存在。然而,使用 operator<< 类型 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 有插入运算符。

我能否确定是否存在一个重载函数,以至于该函数可能不是为特定类型指定的,而是对于给定类型将转换为的某些类型?

您可能只想使用 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 { };

Live on Coliru