Существуют ли подобные скалам миксины для C++?

3 ответа

Решение

Нет, но это может быть подделано в разной степени с помощью шаблонов:

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

Честно говоря, я не проверял это, собирая его, но вы должны понять.

Некоторые аспекты миксинов Scala могут быть реализованы с помощью множественного (виртуального) наследования. К сожалению, это часто создает больше проблем, чем решает. Кроме того, вы не можете смешивать и сочетать суперклассы на лету:

val me = new Human with Coder with Musician

Если вы действительно, действительно хотите настоящие миксины, вам почти нужно использовать что-то вроде шаблонного решения, предложенного в ответе @ Logan Capaldo.

Просто чтобы повторить и расширить то, что упоминалось в предыдущих письмах, позвольте мне сначала дать вам пример того, как реализовать признак Scala Ordered в C++, а затем я покажу, как вы можете смешивать произвольное количество "черт" во время создания экземпляра.

Начнем сначала с упорядоченной черты. Если вы знакомы с Scala SDK, вы заметили, что есть упорядоченная черта. Это используется для обеспечения полного упорядочения посредством реализации простого метода сравнения. В C++ вы можете сделать то же самое следующим образом:

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

Затем, чтобы задать свойство упорядочения для класса C++, вы можете сделать следующее:

class MyOrderedType : public Ordered<MyOrderedType> {
public:
  // Your ctor/dtors, methods
public:
  int compare(const MyOrderedType& that);
};

Очевидно, что вы можете добавлять столько "черт", сколько захотите, но если вы сделаете так, вы не сможете добавлять или удалять черты во время создания экземпляра. Есть ли простое решение для этого? Вид.

Слышали о вариабельных шаблонах C++0x? Это позволяет смешивать столько признаков, сколько вы хотите во время создания шаблона.

Трюк прост, просто объявите ваш хост-класс следующим образом:

template <typename... MIXINS>
class Host : public MIXINS... {
 // Your implementation
};

В чем тут подвох? Ну, проблема в том, что невозможно сделать что-то вроде этого:

template <typename... MIXINS>
class Host : public MIXINS<HOST>... {
    // Your implementation
};

Что в некоторых случаях было бы удобно.

В любом случае, C++ имеет некоторый базовый механизм, который позволяет вам эмулировать некоторые аспекты дополнений Scala. Чего он не может сделать, так это стекового поведения.

НТН.

Другие вопросы по тегам