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

Ответы [ 3 ]

14 голосов
/ 03 февраля 2009

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

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

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

3 голосов
/ 21 августа 2010

Просто чтобы повторить и расширить то, что упоминалось в предыдущих электронных письмах, позвольте мне сначала дать вам пример того, как реализовать признак 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 variadic? Это позволяет смешивать столько признаков, сколько вы хотите во время создания шаблона.

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

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

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

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

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

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

НТН.

3 голосов
/ 03 февраля 2009

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

val me = new Human with Coder with Musician

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

...