Question

I've got this enum type determining a state of an object foo:

enum fooStatus
{
    DOWN = 0,
    TEMPORARY_DOWN = 1,
    UP = 2
};

For this fooStatus enum I've written a basic_ostream operator for backward translation from the enum to a readable form for logging like this:

template<
    typename CH,
    typename TRAITS
>
inline std::basic_ostream<CH, TRAITS>& operator<<(
    std::basic_ostream<CH, TRAITS>& os,
    fooStatus& status
)
{
    switch (status)
    {
        case DOWN:
            os << "DOWN";
            break;

        case TEMPORARY_DOWN:
            os << "TEMPORARY_DOWN";
            break;

        case UP:
            os << "UP";
            break;

        default:
            os << "UNKNOWN STATUS";
            break;
    }
    return os;
}

Now, this worked fine, until I created a static member function of foo, where I wanted to print out all the statuses of all the foo objects I'd had stored.

foo.h:

static std::string get_all_statuses();

foo.cxx:

std::string get_all_statuses() {
    ... 
    std::ostringstream result;
    foreach(foo in fooStorage) { //<-- non c++ simplification
        result << foo->get_status() << ","; /* get_status returns the fooStatus enum type*/
    }
    return result.str();
}

Sadly, this 'get_all_statuses' static function call returns a string containing a number rather than the text defined in the << operator above. Applying the operator upon the member get_status() function in the very same foo.cxx file in foo's member function works just fine. I can't seem to understand some basics here and my colleagues failed to find a solution too.

Hence, my questions are rather two:

First, what is the exact logic behind this behaviour? (expecting something like a compiler not knowing the inline operator at the time of the static function compilation)

Secondly, what would be the best practice approach to make this work as expected?

Était-ce utile?

La solution

Presumably get_status returns a fooStatus by value, which can't be bound to a mutable reference in the signature of operator<<. You need to change fooStatus& to const fooStatus& in your overload of operator<<, which will bind correctly.

#include <iostream>

enum fooStatus
{
    DOWN = 0,
    TEMPORARY_DOWN = 1,
    UP = 2
};

template<
    typename CH,
    typename TRAITS
>
inline std::basic_ostream<CH, TRAITS>& operator<<(
    std::basic_ostream<CH, TRAITS>& os,
    const fooStatus& status
)
{
    switch (status)
    {
        case DOWN:
            os << "DOWN";
            break;

        case TEMPORARY_DOWN:
            os << "TEMPORARY_DOWN";
            break;

        case UP:
            os << "UP";
            break;

        default:
            os << "UNKNOWN STATUS";
            break;
    }
    return os;
}

int main()
{
    std::cout << TEMPORARY_DOWN;
    return 0;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top