2012-12-14 8 views
5

Derzeit habe ich eine Funktionsschablone wie diese, die eine vector in eine string umwandelt (nur eine natürliche Zeichenfolge, die Elemente mit einem Komma trennen):Bessere Möglichkeit, diese Vorlage zu erzwingen?

//the type T must be passable into std::to_string 
template<typename T> 
std::string vec_to_str(const std::vector<T> &vec); 

Wie Sie sehen können, ist dies nur für Vektoren gemeint deren Elemente in die eingebaute in std::to_string Funktion (wie int, double, etc.)

ist es eine gute Praxis mit Kommentaren der erlaubt T zu dokumentieren als bestanden werden? Wenn nicht, was soll ich tun? Ist es möglich, dies besser durchzusetzen?

+0

Natürlich können Sie auch wählen, mit Kommentaren zu dokumentieren und mit einer SFINAE Technik erzwingen. – aschepler

Antwort

2

Seit std::to_string ist eine C++ 11-Funktion, ich denke, man könnte auf eine C++ 11-Lösung offen. In diesem speziellen Fall können Sie den Hinterrückgabetyp in einer sfinae Weise verwenden:

template <typename T> 
auto vec_to_str(const std::vector<T>& vec) -> decltype(std::to_string(std::declval<T>())); 

, die (und zu beseitigen, dass die Überlast), wenn der Wert-Typ für to_string funktioniert nicht ersetzen würden scheitern. Aber das ist nicht unbedingt die angenehmste Art, die Regel zu dokumentieren und durchzusetzen. Es gibt wahrscheinlich auch eine Version des obigen Sfinae-Tricks vor C++ 11, aber es wird nicht hübscher.

Im Allgemeinen würde ich sagen, dass es in Ordnung ist, es in den Kommentaren zu dokumentieren (möglicherweise mit einem Doxygen-Tag, wie \tparam). Sie könnten einen Konzept-Check-Mechanismus im Stil von Boost.Concept-Check verwenden, wenn Sie möchten.

Als Randbemerkung, für diesen speziellen Fall, könnte ich empfehlen, dass Sie die verlassen sich auf std::ostreamoperator << anstelle der to_string Funktion, da es wahrscheinlicher ist, dass benutzerdefinierte Typen (zB ein 2D-Vektor oder etwas) wird ausgestattet sein mit einer Überlastung für die Ausgabe an einen Stream.

0

Bis concepts ankommen, können Sie decltype mit einem anonymen Typ-Parameter verwenden:

template<typename T, 
    typename = decltype(std::to_string(std::declval<T>()))> 
std::string vec_to_str(const std::vector<T> &vec); 
4

Mit static_assert und einigem Ausdruck SFINAE, können Sie eine schöne Kompilierung Fehlermeldung haben:

template<typename T> 
constexpr auto allowed(int) -> decltype(std::to_string(std::declval<T>()), bool()) 
{ 
    return true; 
} 

template<typename> 
constexpr bool allowed(...) 
{ 
    return false; 
} 

template<typename T> 
std::string vec_to_str(const std::vector<T>& vec) 
{ 
    static_assert(allowed<T>(0), "Invalid value type."); 
    return ""; 
} 

struct foo {}; 

int main() 
{ 
    std::vector<int> v_int; 
    vec_to_str(v_int); 

    std::vector<foo> v_double; 
    vec_to_str(v_double);  // static_assert fires here 
} 
Verwandte Themen