2017-09-08 1 views
0

Google Test erklärt ein Templat-Methode PrintTo:mit meiner eigenen Implementierung von Bibliothek Templat-Methode außer Kraft setzen

template <typename T> 
void PrintTo(const T& value, ::std::ostream* os); 

Es gibt mehrere Überlastungen sind ohne Vorlage. Ich habe auch Überladungen für meine benutzerdefinierten Typen hinzugefügt. Dies würde lösen das Problem für viele Qt-Typen

template<typename T> 
void PrintTo(const T &val, ::std::ostream *os) 
{ 
    QString str; 
    QDebug(&str) << val; 
    *os << qUtf8Printable(str); 
} 

:

Mein Problem ist, dass ich wie die Standard-Template-Methode von Google nicht und stattdessen würde Ich mag es so implementieren. Ich kann die Implementierung in Google Tests Code nicht ändern. Ich muss es in meinem eigenen Code neu implementieren.

Mit meiner Vorlage Methode, die ich erhalte diesen Compiler-Fehler:

include/gtest/gtest-printers.h:707:22: error: call of overloaded ‘PrintTo(const QChar&, std::ostream*&)’ is ambiguous 
    PrintTo(value, os); 
        ^
include/gtest/gtest-printers.h:707:22: note: candidates are: 
include/gtest/gtest-printers.h:454:6: note: void testing::internal::PrintTo(const T&, std::ostream*) [with T = QChar; std::ostream = std::basic_ostream<char>] 
void PrintTo(const T& value, ::std::ostream* os) { 
    ^
In file included from tstgoogletest.cpp:51:0: 
googletestqttypes.h:24:6: note: void PrintTo(const T&, std::ostream*) [with T = QChar; std::ostream = std::basic_ostream<char>] 
void PrintTo(const T &val, ::std::ostream *os) 
    ^

Ist es möglich, die auf Vorlagen basierende Methode mit meiner benutzerdefinierten Implementierung auf „Überlast“ ohne jede Art Listing ich verwenden?

QDebug unterstützt bereits Tausende von Typen und ich möchte diese Funktion nicht verpassen!

+0

Beide Template-Funktionen haben die gleiche Signatur und das gleiche Template-Argument - daher kann der Compiler sie nicht unterscheiden. Was ist, wenn Sie Ihre Funktion wie folgt deklarieren: 'template void PrintTo (const C & val, :: std :: ostream * os) {...}'? – vahancho

+1

Ich glaube nicht, dass die Änderung des Argumentnamens irgendetwas verändern würde!Die Compiler-Fehlerausgabe sieht ebenfalls gleich aus. –

+1

'void PrintTo (const QAVariant & value, :: std :: ostream * os);' Kann einige der Typen, nach denen Sie suchen, durch implizite Konvertierung erfassen, andernfalls müssen Sie wahrscheinlich eine separate Funktion für jeden Typ schreiben. –

Antwort

1

Das Problem ist, dass der Compiler die Überladung nicht ausführen kann, da Ihre Funktionssignatur genau die gleiche wie die von Google ist. Sie könnten einen neuen Typ erstellen die Überlastung zB zu erzwingen:

#include <iostream> 

// Google version 
template <class T> 
void print(const T& value, std::ostream& os) { 
    os << "Google print: " << value << std::endl; 
} 

// My wrapper type 

template <class T> 
struct PrintWrap { 
    const T& value_; 

    PrintWrap(const T& value): value_(value){} 
}; 

template <class T> 
PrintWrap<T> printWrap(const T& value) { 
    return PrintWrap<T>(value); 
} 


template <class T> 
void print(const PrintWrap<T>& printWrap, std::ostream& os) { 
    os << "My special print: " << printWrap.value_ << std::endl; 
} 

int main() { 
    std::string value = "Hallo world"; 
    print(printWrap(value), std::cout); 

    // your code goes here 
    return 0; 
} 

Im Falle Sie nicht die Kontrolle über den anrufenden Code, können Sie die notwendigen Funktionen in printWrap zB Bediener erforderlich Überlastung == unter Überlastung, wie dies die Bibliotheksfunktion (checkEqualTo) erfordert:

#include <iostream> 

// Google version 
template <class T> 
void print(const T& value, std::ostream& os) { 
    os << "Google print: " << value << std::endl; 
} 

// My wrapper type 
// :NOTE Overload what is required by Google, in this 
// case lets assume operator== as example 
template <class T> 
struct PrintWrap { 
    const T& value_; 
    PrintWrap(const T& value): value_(value){} 

    friend bool operator==(const PrintWrap& lhs, const PrintWrap& rhs) { 
    return lhs.value_ == rhs.value_; 
    } 
}; 

template <class T> 
PrintWrap<T> printWrap(const T& value) { 
    return PrintWrap<T>(value); 
} 


template <class T> 
void print(const PrintWrap<T>& printWrap, std::ostream& os) { 
    os << "My special print: " << printWrap.value_ << std::endl; 
} 

template <class T> 
bool checkEqualTo(const T& lhs, const T& rhs) { 
    if (lhs == rhs) return true; 
    print(lhs, std::cout); 
    print(rhs, std::cout); 
    return false; 
} 

// Google code... 
#define CHECK_EQUAL(x,y) checkEqualTo(x,y) 

int main() { 
    std::string value = "Hallo world"; 
    CHECK_EQUAL(printWrap(value), printWrap(value)); 

    return 0; 
} 

EDIT

Sie auch einen Blick auf diese guide haben kann, die Dokumentation Gtest der ist con cerning print customization, bei der PrintTo im selben Namespace wie der fragliche Typ definiert wird, um ADL (Argument Dependent Lookup) zu verwenden.

Im Folgenden ein Beispiel für die Verwendung ADL für diesen Zweck ist, das, was sie für die Erweiterung ins Auge gefasst als Mechanismus ist, wäre es naht:

#include <iostream> 
#include <cassert> 

// Google version template <class T> 
void print(const T& value, std::ostream& os) { 
    os << "Google print: " << value << std::endl; 
} 

namespace custom { 

template <class T> 
struct Printable : T 
{ 
    template <class...Args> 
    Printable(Args&&... args) 
    : T(std::forward<Args>(args)...) 
    { } 
}; 

template <class T> 
void print(const Printable<T>& value, std::ostream& os) { 
    os << "My special print: " << value << std::endl; 
} 

} //custom 

int main() { 
    custom::Printable<std::string> x = "my string"; 
    custom::Printable<std::string> y = "my other string"; 

    assert(! (x == y)); 

    //found by ADL  
    print(x, std::cout); 
    return 0; 
} 

Hier oben, die Funktionsdeklaration im gleichen Namensraum wie das Argument Lookup-Vorrang, und daher existiert die Mehrdeutigkeit nicht. Sie müssen keine Druckversion verwenden (es gibt möglicherweise eine bessere vollständige Implementierung). Sie könnten je nach Bedarf einen Druck pro Typ haben.

Beachten Sie, dass der obige Code mein Beispiel ist. Gtest erfordert die Überlastung zu sein:

void PrintTo(const Bar& bar, ::std::ostream* os)... 

Darüber hinaus erhalten Sie nur Operator < < für Ihre Art überlasten könnten, wie in ihrer Dokumentation erwähnt.

+0

Ich rufe 'PrintTo' nicht selbst an. Dies ist Teil des Testrahmens. Ich platziere ein Makro wie 'ASSERT_EQ (links, rechts)' und irgendwo tief in googles Code wird ein Aufruf von 'PrintTo' mit' left' oder 'right' aufgerufen. –

+0

Sind Sie sicher, dass es keine andere Lösung gibt? Ich möchte diese Wrap-Methoden nicht bei jedem Test schreiben. Wir haben bereits Hunderte von Tests und ich möchte sie nicht alle ändern. EDIT: Ich glaube, ich antwortete auf einen gelöschten Kommentar ... –

+0

Ich habe mein Beispiel geändert, um zu zeigen, wie Sie das Problem ASSERT_EQ überwinden können –

Verwandte Themen