I am writing a template class where I need a method to print out element class into stdout. But I am having a problem writing it - what if cout << or operator const char*() is not defined or overloaded in my element class?

Is there a way to find it out to maybe throw an exception and not get compilation error?

有帮助吗?

解决方案

If the operator is not overloaded, your program can not compile. This is a compile time error and there is no way to delay that until runtime.

A way around would be to not use an operator, but a function pointer. If the operation is not supported, than the function pointer could be set to 0 which you can detect at runtime.

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

This example uses C++11 and <functional>. For C++03 you would have to use a "normal" function pointer.

其他提示

You might use some SFINAE to test if an (formatted) output operator exists:

#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)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top