2010-02-24 8 views
6

se tenga lo siguiente:¿Eliminar la repetición en el código 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; 
} 

¿hay una manera de eliminar la repetición? Quiero usar las plantillas, pero sólo lo quieren para los siguientes tipos: const char * int, sin firmar, y size_t

+0

@anon: ¿Lo quiere solo para estos tipos o también es aceptable para otros tipos? En otras palabras, si intenta usar algún otro tipo, ¿qué debería pasar? Un error del compilador o un no- op o push_back() en el vector? – Naveen

+1

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

+1

@Clifford: Pero ninguno de ellos es tan sexy como la solución de la mina :) – GManNickG

Respuesta

6

Realmente, en "vainilla" C++ ya sea escribir a mano, para tipos específicos, o utilizar una plantilla como sugerida dirkgently.

Dicho esto, si se puede usar Boost que esto hace lo que quiere:

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; 
} 

Esto generará un error en tiempo de compilación con el mensaje TYPE_NOT_ALLOWED incrustado en él si el tipo está compilado no está contenida en el lista de tipos

Además, como esta respuesta requiere Boost acabo de utilizar lexical_cast. Notarás que estás repitiendo ese código, y eso es malo. Considere wrapping esa funcionalidad en una función.


Si no está capaz de usar Boost, puede simular esto con bastante facilidad con algunos rasgos de 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; 
} 

Esto también generará un error en tiempo de compilación si falla la aserción , aunque el código no es tan sexy. :(< - No es sexy

+1

Y desafortunadamente el error del compilador podría no ser sexy tampoco :) –

1

Algo como esto debería funcionar:

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

pero OP lo quiere solo para tipos particulares. – Naveen

+0

@Naveen: No estoy seguro si quiere una plantilla restringida o si esos son los únicos _ tipos que necesita. Alguna aclaración será de ayuda. – dirkgently

+0

@ *: FWIW, puede buscar tipos específicos con Boost.Type Traits y 'BOOST_STATIC_ASSERT'. – dirkgently

Cuestiones relacionadas