有没有办法找出一个类是否有一个重载运算符?

时间:2014-04-08 08:52:39

标签: c++ class overloading

我正在编写一个模板类,我需要一个方法将元素类打印到stdout。但是我在编写它时遇到了问题 - 如果我的元素类中没有定义或重载cout <<operator const char*()会怎么样?

有没有办法找到它可能会抛出异常而不会出现编译错误?

2 个答案:

答案 0 :(得分:1)

如果操作符未重载,则程序无法编译。这是编译时错误,在运行时之前无法延迟。

一种方法是不使用运算符,而是使用函数指针。如果不支持该操作,则可以将函数指针设置为0,您可以在运行时检测该函数。

class A {
public:
    int q; // some data

    typedef std::function<void(std::ostream& os, const A&)> PrinterFunc;
    PrinterFunc func;

    friend std::ostream& operator<<(std::ostream& os, const A& a) {
        if(!a.func) {
            throw "Not supported";
        }
        func(os,a);
        return os;
    }
};

A a;
a.func = [](std::ostream& os, const A& a) { os << "hello " << a.q; }
std::cout << a << std::endl; // will print

A b;
std::cout << b << std::endl; // will throw

此示例使用C ++ 11和<functional>。对于C ++ 03,您必须使用“普通”函数指针。

答案 1 :(得分:1)

您可以使用某些SFINAE来测试(格式化的)输出运算符是否存在:

#include <iostream>

// HasFormattedOutput
// ============================================================================

namespace HasFormattedOutput {

    namespace Detail
    {
        struct Failure{};
    }

    template<typename OutputStream, typename T>
    Detail::Failure operator << (OutputStream&, const T&);

    template<typename OutputStream, typename T>
    struct Result : std::integral_constant<
        bool,
        ! std::is_same<
            decltype(std::declval<OutputStream&>() << std::declval<T>()),
            Detail::Failure
        >::value
    > {};
} // namespace HasFormattedOutput

template <typename T, typename OutputStream = std::ostream>
struct has_formatted_output : std::conditional<
    HasFormattedOutput::Result<OutputStream, T>::value,
    std::true_type,
    std::false_type>::type
{};

// Test
// ============================================================================

struct X {};
int main() {
    std::cout.setf(std::ios_base::boolalpha);
    std::cout << has_formatted_output<const char*>() << '\n';
    std::cout << has_formatted_output<X>() << '\n';
}

(C ++ 11)