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

时间:2016-06-21 20:48:45

标签: c++ metaprogramming

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

我是否可以确定存在重载函数,以便不能为特定类型指定函数,但对于某些类型,给定类型将转换为?

1 个答案:

答案 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 { };

Live on Coliru