문제

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