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?

Was it helpful?

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;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top