2010-02-24 3 views
6

Dati i seguenti:Eliminare la ripetizione nel codice C++?

StreamLogger& operator<<(const char* s) { 
    elements.push_back(String(s)); 
    return *this; 
} 

StreamLogger& operator<<(int val) { 
    elements.push_back(String(asString<int>(val))); 
    return *this; 
} 

StreamLogger& operator<<(unsigned val) { 
    elements.push_back(String(asString<unsigned>(val))); 
    return *this; 
} 

StreamLogger& operator<<(size_t val) { 
    elements.push_back(String(asString<size_t>(val))); 
    return *this; 
} 

c'è un modo per eliminare la ripetizione? Voglio utilizzare i modelli, ma io lo voglio solo per i seguenti tipi: const char * int, unsigned, e size_t

+0

@anon: lo vuoi solo per questi tipi o è accettabile anche per altri tipi? In altre parole, se provi a usare un altro tipo cosa dovrebbe accadere? Un errore del compilatore o un no op o push_back() nel vettore? – Naveen

+1

Duplicato: http://stackoverflow.com/questions/148373/c-restrict-template-function – Clifford

+1

@Clifford: Ma nessuno di questi è sexy come la mia soluzione :) :) – GManNickG

risposta

6

Davvero, in C "vanilla" ++ voi o scrivi la mano, per tipi specifici, o usi un modello come suggerito da dirkentemente.

Detto questo, se si può usare Boost che fa ciò che si vuole:

template <class T> 
StreamLogger& operator<<(T val) 
{ 
    typedef boost::mpl::vector<const char*, int, 
           unsigned, size_t> allowed_types; 

    BOOST_MPL_ASSERT_MSG(boost::mpl::contains<allowed_types, T>::value, 
          TYPE_NOT_ALLOWED, allowed_types); 

    // generic implementation follows 
    elements.push_back(boost::lexical_cast<std::string>(val)); 

    return *this; 
} 

Questo genererà un errore di compilazione con il messaggio TYPE_NOT_ALLOWED incorporato in esso se il tipo in fase di compilazione non è contenuta nel TypeList.

Inoltre, poiché questa risposta richiede Boost, ho usato solo lexical_cast. Noterai che stai ripetendo quel codice, e questo è male. Considerare wrapping tale funzionalità in una funzione.


Se non sei in grado di utilizzare Boost, è possibile simulare questo abbastanza facilmente con alcuni tratti del tipo:

template <typename T, typename U> 
struct is_same 
{ 
    static const bool value = false; 
}; 

template <typename T> 
struct is_same<T, T> 
{ 
    static const bool value = true; 
}; 

template <bool> 
struct static_assert; 

template <> 
struct static_assert<true> {}; // only true is defined 

// not the best, but it works 
#define STATIC_ASSERT(x) static_assert< (x) > _static_assert_ 

template <class T> 
StreamLogger& operator<<(T val) 
{ 
    STATIC_ASSERT(is_same<const char*, T>::value || 
        is_same<int, T>::value || 
        is_same<unsigned, T>::value || 
        is_same<size_t, T>::value); 

    // generic implementation follows 
    elements.push_back(boost::lexical_cast<std::string>(val)); 

    return *this; 
} 

Questo sarà anche generare un errore di compilazione se l'asserzione non riesce , anche se il codice non è così sexy. :(< - Non sexy

+1

E sfortunatamente l'errore del compilatore potrebbe non essere sexy :) –

1

Qualcosa del genere dovrebbe funzionare:

template <class T> 
StreamLogger& operator<<(T val) { 
    istringstream s; 
    s << val; 
    elements.push_back(s.str()); // assuming elements is a vector<string> 
    return *this; 
} 
+0

ma OP lo vuole solo per tipi particolari. – Naveen

+0

@Naveen: Non sono sicuro se desidera un modello limitato o se questi sono i tipi _only di cui ha bisogno. Alcuni chiarimenti saranno d'aiuto. – dirkgently

+0

@ *: FWIW, il controllo di tipi particolari può essere eseguito con Boost.Type Trits e 'BOOST_STATIC_ASSERT'. – dirkgently