2013-06-16 14 views
16

C++ non ha un modo per ottenere la rappresentazione della stringa di un enum. La gente aggirare questo scrivendo funzioni personalizzate che contengono un sacco di codice boilerplate aka
switch con case XYZ return "XYZ";Sostituisce std :: to_string per le enumerazioni definite dall'utente il modo corretto di fornire to_string per le enumerazioni definite dall'utente?

Questo naturalmente richiede agli utenti del enum di conoscere il nome della funzione personalizzata.

Quindi ho pensato di aggiungere una specializzazione a std::to_string per consentire a un utente di utilizzare to_string sulle mie enumerazioni. Qualcosa di simile:

// 
#include <iostream> 
#include <string> 
#include <cassert> 
#define TEST 
class Car 
{ 
public: 
    enum class Color 
    { 
     Red, 
     Blue, 
     White 
    }; 
}; 
#ifdef TEST 
#include <string> 
namespace std 
{ 
    std::string to_string (Car::Color c) 
    { 
     switch (c) 
     { 
     case Car::Color::Red: 
      return "Red"; 
     case Car::Color::Blue: 
      return "Blue"; 
     case Car::Color::White: 
      return "White"; 
     default: 
      { 
       assert(0); 
       return ""; 
      } 
     } 
    } 

} 
#endif 
int main() 
{ 
    std::cout << std::to_string(Car::Color::White) << std::endl; 

} 

Ci sono problemi con questa soluzione?

+4

Non penso che sia possibile sovraccaricare le funzioni std, solo modelli specializzati. – chris

+0

Due cose: vorrei controllare l'uso di '#define str (x) # x' (e l'associato' #define glue (a, b) a ## b') per vedere se ciò si adatta alle tue esigenze con meno boilerplate . Assicurati di racchiuderlo in una funzione per la sicurezza del tipo e di "# undef" subito dopo aver terminato. In secondo luogo, e meno importante, hai dimenticato il 'break;' s nel tuo switch - probabilmente dando una ragione per non usarne uno se non ti senti super-testy. – FizzixNerd

risposta

22

Questo non è "override" (che si applica alle funzioni virtual) e non è stata aggiunta una "specializzazione" (che si applica ai modelli), è stato aggiunto un sovraccarico, che aggiunge una dichiarazione e la definizione di una nuova funzione per namespace std e che è vietato:

17.6.4.2.1 namespace std [namespace.std]
Il comportamento di un programma C++ è indefinito se si aggiunge dichiarazioni o definizioni per namespace std o ad una spazio dei nomi all'interno del namespace std se non diversamente specificato. Un programma può aggiungere una specializzazione di modello per qualsiasi modello di libreria standard allo std dei nomi solo se la dichiarazione dipende da un tipo definito dall'utente e la specializzazione soddisfa i requisiti di libreria standard per il modello originale e non è esplicitamente vietata.

Una soluzione migliore sarebbe quella di sovraccaricarlo nel proprio spazio dei nomi, e chiamare to_string(c) invece di std::to_string(c). Ciò troverà la funzione giusta e non è necessario aggiungere nulla a std

+0

wait, im confused, come intendi "che aggiunge una dichiarazione e definizione di una nuova funzione allo spazio dei nomi std" ... to_string esiste in std, giusto? consideri i parametri parte della funzione, ecco perché la chiami nuova? – NoSenseEtAl

+0

Sì, è una nuova funzione, non è vero? Non era lì prima. Non è un nuovo _name_ ma stai definendo una nuova funzione. La funzione 'std :: to_string (int)' è una funzione diversa da 'std :: to_string (double)' e una funzione diversa da 'std :: to_string (Car :: Color)' –

+3

Lo standard C++ considera la parte dei tipi di parametro anche della funzione, non sono solo io: ** 1.3.17 [firma defns.signature] ** nome, elenco tipo di parametro (8.3.5) e racchiuso spazio dei nomi (se presente) –

Problemi correlati