3 Stimmen

Boost.Test `output_test_stream` schlägt mit dem Template-Ausgabeoperator fehl

Ich habe eine Klasse:

class foo {
private:
    std::string data;
public:
    foo &append(const char* str, size_t n) { data.append(str,n); }

    // für Debug-Ausgabe
    template 
    friend T& operator<< (T &out, foo const &f);

    // etwas anderes
};

template 
T& operator<< (T &out, foo const &f) {
    return out << f.data;
}

Ich möchte, dass dies mit jeder Klasse funktioniert, die den << Operator bereitstellt.

Dies funktioniert gut mit std::cout wie folgt:

std::cout << fooObject;

Aber das folgende scheitert:

BOOST_AUTO_TEST_CASE( foo_append_and_output_operator )
{
    // fooObject ist hier zugänglich
    const char* str = "hallo";
    fooObject.append(str, strlen(str));

    output_test_stream output;
    output << fooObject;

    BOOST_CHECK( output.is_equal(str) );
}

g++ sagt mir, dass:

In function ‘T& operator<<(T&, const foo&) 
    [with T = boost::test_tools::output_test_stream]’:
error: invalid initialization of reference of type
    ‘boost::test_tools::output_test_stream&’ from expression of type
    ‘std::basic_ostream >’

Was passiert hier?

Ich benutze Boost 1.34.1 auf Ubuntu 8.04.

3voto

mkluwe Punkte 3463

Sie wissen vielleicht schon, aber output_test_stream als std::ostream zu verwenden, funktioniert:

class foo {
    // [...]
    friend
    std::ostream& operator<< ( std::ostream &os, const foo &f );
};

std::ostream& operator<< ( std::ostream &os, const foo &f ) {
    return os << f.data;
}

3voto

Björn Pollex Punkte 72424

Also ich denke, ich habe eine Erklärung, aber noch keine Lösung. output_test_stream implementiert seine Stream-Funktionalität, indem es wrap_stringstream untergeordnet ist. Der Einfügeoperator dafür ist eine freie Funktionsvorlage, die so aussieht:

template 
inline basic_wrap_stringstream&
operator<<( basic_wrap_stringstream& targ, T const& t )
{
    targ.stream() << t;
    return targ;
}

// ... weiter unten im selben Header

typedef basic_wrap_stringstream       wrap_stringstream;

Dein Operator wird mit output_test_stream als Stream-Typ aufgerufen, und das ist auch sein Rückgabetyp. Dein Operator ruft dann den obigen Operator auf und gibt einfach den Rückgabewert weiter. Der Rückgabewert des obigen Operators ist jedoch eine Oberklasse des Rückgabetyps deines Operators. Wenn der Compiler versucht, die Referenz zu erstellen, die du zurückgeben möchtest, stößt er darauf, dass er eine Referenz auf eine Unterklasse nicht von einer Referenz auf eine Oberklasse initialisieren kann, selbst wenn beide auf dasselbe Objekt verweisen. Macht das Sinn?

0voto

mkluwe Punkte 3463

Ist es ein Tippfehler? Du hast geschrieben

foo.append(str, strlen(str));

aber foo ist der Name der Klasse und nicht eines Objekts.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X