Существуют ли scala -подобные mixins для С++?
Ответ 1
Нет, но он может быть подделан в разной степени с помощью шаблонов:
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>);
}
Чтобы быть абсолютно честным, я не тестировал это, компилируя его, но вы должны получить эту идею.
Ответ 2
Некоторые аспекты Scala mixins могут быть выполнены с использованием множественного (виртуального) наследования. К сожалению, это часто вводит больше проблем, чем решает. Кроме того, вы не можете смешивать и сопоставлять суперклассы на лету a la:
val me = new Human with Coder with Musician
Если вы действительно хотите действительно настоящих миксинов, вам почти нужно пойти с чем-то вроде решения шаблона, предложенного в ответ, Logan Capaldo.
Ответ 3
Чтобы повторить и расширить то, что упоминалось в предыдущих письмах, позвольте мне сначала привести пример реализации Scala Упорядоченный признак на С++, а затем дать мне возможность показать, как вы можете смешивать произвольное количество "признаков", во время создания экземпляра.
Начнем сначала с символа "Заказ". Если вы знакомы с SDK Scala, вы заметите, что есть атрибут Ordered. Это используется для обеспечения полного упорядочения с помощью простого метода сравнения. В С++ вы можете сделать то же самое:
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; }
};
Затем, чтобы присвоить свойство упорядочения классу С++, вы можете сделать следующее:
class MyOrderedType : public Ordered<MyOrderedType> {
public:
// Your ctor/dtors, methods
public:
int compare(const MyOrderedType& that);
};
Очевидно, вы можете смешивать столько "признаков", сколько хотите, но если вы сделаете так, вы не сможете добавлять или удалять черты во время создания экземпляра. Есть ли простое решение для этого? Вид-оф.
Вы слышали о вариативных шаблонах С++ 0x? Это обеспечивает способ смешивания как можно большего количества признаков во время создания шаблона.
Трюк прост, просто объявите свой хост-класс следующим образом:
template <typename... MIXINS>
class Host : public MIXINS... {
// Your implementation
};
Какая уловка здесь? Ну, проблема в том, что невозможно сделать что-то вроде этого:
template <typename... MIXINS>
class Host : public MIXINS<HOST>... {
// Your implementation
};
Что в некоторых случаях было бы удобно.
В любом случае С++ имеет некоторый базовый механизм, который позволяет эмулировать некоторые аспекты Scala Mix-ins. Однако это не может быть поведение стекирования.
НТН.