2016-07-24 27 views
1
#include <string> 
#include <type_traits> 

using namespace std; 

template 
< 
    typename CharT, 
    template<typename> class Traits, 
    template<typename> class Allocator, 
    typename RightT, 
    typename StringT = basic_string 
    < 
    CharT, 
    Traits<CharT>, 
    Allocator<CharT> 
    > 
> 
enable_if_t 
< 
    is_constructible<StringT, RightT>::value, 
    StringT& 
> 
operator <<(StringT& lhs, const RightT& rhs) 
{ 
    return lhs.append(rhs); 
} 

int main() 
{ 
    string s1, s2; 
    s1 << s2; // compilation error! 

    return 0; 
} 

Mein Compiler ist VS 2015 Update 3 Die Kompilation Fehlermeldung lautet:Warum funktioniert es nicht, "operator <<" auf std :: string zu überladen?

Fehler: ungültige Operanden binäre Ausdruck ('string' (aka 'basic_string, Allocator>') und ‚string ')

Warum funktioniert es nicht wie erwartet?

+3

Dies ist genau das, was 'Operator +' ist für – user4759923

+0

Nein. Es ist nicht das gleiche wie 'Operator + ', aber ähnlich wie' operator + = '. Operator '' kann jedoch tun: 's1 << s2 << s3 << ...', während 'operator + =' nicht kann. – xmllmx

+0

@xmllmx Warum versuchen Sie, dies tatsächlich mit einer Vorlage zu überladen? –

Antwort

4

Hat der Compiler Ihnen mehr Informationen als diese einzelne Zeile gegeben? Etwas wie:

26:1: note: template argument deduction/substitution failed: 
35:11: note: couldn't deduce template parameter 'CharT' 

Wenn Sie

operator <<(StringT & lhs, const RightT& rhs) 

mit

operator <<(basic_string<CharT, Traits<CharT>, Allocator<CharT>>& lhs, const RightT& rhs) 

es kompiliert ersetzen.

Grundsätzlich stellen Sie den Wagen vor das Pferd. Sie können Vorlagenargs verwenden, um eine Standardvorlage zu erstellen. Arg (StringT = ...) Wenn Sie die Vorlagenargumente bereits kennen. Sie können den Standardwert nicht zum Ermitteln der Argumente verwenden.

Wenn Sie sowohl basic_string als auch andere/benutzerdefinierte Zeichenfolgen unterstützen möchten, müssen Sie möglicherweise zwei Spezialisierungen oder etwas schreiben.

Oder erkennen Sie, was Ihre Template-Anforderungen wirklich sind - Sie benötigen kein Constructible, Sie benötigen "Anfügbar", also SFINAE und ignorieren, ob es ein basic_string oder MyCustomString ist - es spielt keine Rolle; das einzige, was zählt, ist, ob lhs.append(rhs) funktioniert (und, äh, vielleicht herausfinden, seine Rückmeldung auch ...)