c++ - petromyzontiformes - nombres de peces agnatos
¿Hay mixinas tipo Scala para C++? (3)
No, pero se puede simular en distintos grados con plantillas:
template<typename AbsIterator>
class RichIterator : public AbsIterator {
public:
template<typename FuncType>
void foreach(FuncType f) { while( hasNext() ) f( next() ); }
};
class StringIterator {
std::string m_s;
int i;
public:
typedef char T;
StringIterator() : m_s(), i(0) {} // Unfortunately need this, or
// else RichIterator
// gets way more complicated
StringIterator(const std::string &s) : m_s(s), i(0) {}
void swap(StringIterator& other) {
m_s.swap(other.m_s);
std::swap(i, other.i);
}
void reset_str(const std::string& s) {
StringIterator(s).swap(*this);
}
bool hasNext() { return i < m_s.length(); }
char next() { return m_s[i++]; }
};
template<typename Outputable>
void println(const Outputable& o) {
std::cout << o << std::endl;
}
int main(int argc, char **argv) {
typedef RichIterator<StringIterator> Iter;
Iter iter;
iter.reset_str(argv[1]);
iter.foreach(&println<Iter::T>);
}
Para ser totalmente honesto, no he probado esto compilándolo, pero debes tener la idea.
Solo para reiterar y ampliar lo mencionado en correos electrónicos anteriores, déjame darte primero un ejemplo de cómo implementar el rasgo de Scala Ordered en C ++ y luego déjame mostrarte cómo puedes mezclar un número arbitrario de "rasgos" en el momento de la instanciación.
Comencemos primero con el rasgo Ordenado. Si está familiarizado con el SDK de Scala, habrá notado que hay un rasgo Ordenado. Esto se utiliza para proporcionar un orden total mediante la implementación de un método simple de "comparación". En C ++, podría hacer lo mismo de la siguiente manera:
template <typename T>
class Ordered {
public:
virtual int32_t compare(const T& that) = 0;
bool operator >(const T& that) {return this->compare(that) == 1; }
bool operator >=(const T& that) {return this->compare(that) >= 0; }
bool operator ==(const T& that) { return this->compare(that) == 0; }
bool operator <=(const T& that) {return this->compare(that) <= 0; }
bool operator <(const T& that) {return this->compare(that) == -1; }
};
Luego, para dar una propiedad de pedido a una clase de C ++, puede hacer lo siguiente:
class MyOrderedType : public Ordered<MyOrderedType> {
public:
// Your ctor/dtors, methods
public:
int compare(const MyOrderedType& that);
};
Obviamente, puedes mezclar tantos "rasgos" como quieras, pero si lo haces de esta manera, no puedes agregar o eliminar rasgos en el momento de la instanciación. ¿Hay una solución simple para esto? Mas o menos.
¿Has oído hablar de las plantillas variadas de C ++ 0x? Esto proporciona una manera de mezclar tantos rasgos como desee en el momento de creación de instancias de la plantilla.
El truco es simple, solo declara tu clase de host de la siguiente manera:
template <typename... MIXINS>
class Host : public MIXINS... {
// Your implementation
};
¿Cuál es la trampa aquí? Bueno, el problema es que no es posible hacer algo como esto:
template <typename... MIXINS>
class Host : public MIXINS<HOST>... {
// Your implementation
};
Que en algunos casos hubiera sido útil.
En cualquier caso, C ++ tiene un mecanismo básico que le permite emular algunos aspectos de los Mix-ins de Scala. Lo que no puede hacer, sin embargo, es el comportamiento de apilamiento.
HTH.
Algunos aspectos de Scala mixins se pueden satisfacer usando herencia múltiple (virtual). Desafortunadamente, esto a menudo presenta más problemas de los que resuelve. Además, no puede mezclar y combinar superclases sobre la marcha a la :
val me = new Human with Coder with Musician
Si realmente quieres verdaderas mezclas, casi tienes que elegir algo como la solución de plantilla propuesta en la respuesta de @ Logan Capaldo .