2016-05-09 17 views
1

Ich schreibe eine Bibliothek und es sollte Objekte zu string.Probleme mit Überladung Auflösung und Operator << für Vorlagenvorlagen

Ich habe gewählt, operator<<(ostream&... zu unterstützen.

Eine andere Sache ist, dass meine Bibliothek Standard-Stringifikation von Typen, die nicht operator<<(ostream&... in der {?} Form haben sollte.

Das Problem ist mit Templat-Typen wie vector<> - Ich will nicht der Benutzer 2 Überlastungen für vector<int> und vector<float> schreiben - aber ich kann es nicht zu arbeiten. Hier

ist der Code:

#include <string> 
#include <type_traits> 
#include <sstream> 
#include <vector> 
#include <iostream> 
using namespace std; 

namespace has_insertion_operator_impl { 
    typedef char no; 
    typedef char yes[2]; 

    struct any_t { 
     template <typename T> 
     any_t(T const&); 
    }; 

    no operator<<(ostream const&, any_t const&); 

    yes& test(ostream&); 
    no test(no); 

    template <typename T> 
    struct has_insertion_operator { 
     static ostream& s; 
     static T const&  t; 
     static bool const value = sizeof(test(s << t)) == sizeof(yes); 
    }; 
} 

template <typename T> 
struct has_insertion_operator : has_insertion_operator_impl::has_insertion_operator<T> {}; 

template <class T> 
typename enable_if<has_insertion_operator<T>::value, string>::type stringify(const T& in) { 
    stringstream stream; 
    stream << in; 
    return stream.str(); 
} 

template <class T> // note the negation here compared to the one above 
typename enable_if< ! has_insertion_operator<T>::value, string>::type stringify(const T&) { 
    return "{?}"; 
} 

// USER CODE: 

struct myType {}; 

ostream& operator<<(ostream& s, const myType&) { s << "myType"; return s; } 

template<typename T> 
ostream& operator<<(ostream& s, const vector<T>&) { s << "vector<T>"; return s; } 

int main() { 
    myType a;   cout << stringify(a) << endl; // prints "myType" 
         cout << stringify(6) << endl; // prints "6" 
    vector<int> v(5); cout << stringify(v) << endl; // prints "{?}" instead of "vector<T>" 

    return 0; 
} 

myType und die ganze Zahl sowohl Zeichenfolge erhalten, aber für die vector<int> erhalte ich den Standard {?}.

Ich brauche Hilfe dabei - es ist ein Showstopper für mich. Ich brauche von Benutzern bereitgestellte operator<<(ostream&... Überladungen, out-of-the-Box ohne Änderung zu arbeiten - und das alles in C++ 98.

+1

_ "meine Header wird noch nichts mit ihnen ziehen - nicht einmal oder sogar " _ Twofold: 1. [Vorwärtsdeklarationen] (http://stackoverflow.com/questions/625799/resolve-header-include-circular -dependencies-in-c) 2. [Template-Implementierungen] (http://stackoverflow.com/questions/495021/why-can-templates-only-be-implementiert-in-the-header-file). Vielleicht ist das nur eine dumme Einschränkung. Könnten Sie bitte etwas über die Gründe sagen, warum? –

+0

Bitte geben Sie eine [mcve] an. Schwerpunkt auf minimal. Sie benötigen keine 140 Codezeilen, die auf drei Dateien verteilt sind, um das Problem zu reproduzieren, das Sie sehen. – Barry

+1

Auch absolut "" vorziehen, um manuell alle "Std" -Typen selbst zu deklarieren. Das ist der Zweck der Existenz dieses Headers. – Barry

Antwort

0

stellte sich heraus, alles, was ich tun musste, war den Namensraum mit der Umsetzung des Einfügeoperator Merkmal entfernen so die Fallback operator<<(ostream&... endet im globalen Umfang - erklärt here.

1

Passend den Vektor Sie bessere Kandidaten für Ihre stringize Funktionen

Für C 11 ++ dies wäre zur Verfügung stellen müssen:

template <template <typename...> class V, typename... Args> 
typename enable_if< !has_insertion_operator<V<Args...>>::value, string>::type stringify(const V<Args...>&) { 
    return "template {?}"; 
} 
// also add enable_if for yes with code identical to the one in template<typename T> 

Da Sie ++ 98 brauchen C, ich fürchte, Sie müssen eine Anzahl von Template-Überladungen für 1 bis N (etwa 5 oder 10) Args bereitstellen. So was.

template <template <typename> class V, typename T0> 
... 
template <template <typename, typename> class V, typename T0, typename T1> 
... 
/// etc 

Zum Beispiel vector in Ihrem Fall hat 2 Vorlagenargumente, und das zweite Paar von yes/no Funktionen entsprechen