Есть ли подобные scala mixins для C++?

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

  • mapToChar(n) отображает число n в представление символа, для Например, 10 отображается на «A».

  • convertToBaseN(n, base) преобразует число n в его представление по заданному base. Этот метод использует рекурсивный подход и использует предыдущий.

  • Наконец, generateNumbersOfBase(base, start, size) генерирует массив из size элементов, начиная с номера start для данного base.

КОД:

// Next utility method map a decimal number to a character representation.

const mapToChar = (n) =>
{
    n = (n >= 0 && n <= 9) ? '0'.charCodeAt() + n : n - 10 + 'A'.charCodeAt();
    return String.fromCharCode(n);
}

// Next utility method convert a decimal number to his base-n representation.

const convertToBaseN = (n, base, res = "") =>
{
    if (n <= 0)
       return (res && res.split("").reverse().join("")) || "0";

    // Convert input number to given base by repeatedly 
    // dividing it by base and taking remainder.

    res += mapToChar(n % base);
    return convertToBaseN(Math.floor(n / base), base, res);
}

// Next method generates an array of numbers for a given base.

const generateNumbersOfBase = (base, start, size) =>
{
    return Array(size).fill(0).map((x, idx) => convertToBaseN(start + idx, base));
}

// Finally, generate some arrays.

let base10Array = generateNumbersOfBase(10, 15, 5);
let base2Array = generateNumbersOfBase(2, 5, 9);
let base16Array = generateNumbersOfBase(16, 10, 12);
let base8Array = generateNumbersOfBase(8, 1, 12);

console.log(
    JSON.stringify(base10Array),
    JSON.stringify(base2Array),
    JSON.stringify(base16Array),
    JSON.stringify(base8Array),
);

Теперь, если вам нужно преобразовать некоторое представление base-n обратно в десятичное число, вы можете использовать следующий подход:

const convertToDec = (str, base) =>
{
    let codeA = 'A'.charCodeAt();
    let code0 = '0'.charCodeAt();

    return str.split("").reverse().reduce((acc, c, idx) =>
    {
        let code = c.charCodeAt();
        c = code + ((c >= '0' && c <= '9') ? -code0 : -codeA + 10);
        return acc += c * Math.pow(base, idx);
    }, 0);
}

// Lets convert back some arrays generated on the previous exampel

let base2Array = ["101","110","111","1000","1001","1010","1011","1100","1101"];
let base16Array = ["A","B","C","D","E","F","10","11","12","13","14","15"];

let res2 = base2Array.map(x => convertToDec(x, 2));
let res16 = base16Array.map(x => convertToDec(x, 16));

console.log(
    JSON.stringify(res2),
    JSON.stringify(res16)
);

21
задан davka 17 May 2011 в 05:32
поделиться

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

Чтобы быть полностью честным, я имею, не протестировали это путем компиляции его, но необходимо получить идею.

14
ответ дан 29 November 2019 в 21:54
поделиться

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

val me = new Human with Coder with Musician

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

3
ответ дан 29 November 2019 в 21:54
поделиться

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

Начнем сначала с трейта «Упорядоченный». Если вы знакомы с Scala SDK, вы заметили, что есть черта Ordered. Это используется для обеспечения полного упорядочения посредством реализации простого метода «сравнения». В 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 ++ имеет некоторый базовый механизм, который позволяет вам имитировать некоторые аспекты Mix-ins Scala. Однако чего он не может сделать, так это поведения стекирования.

HTH.

3
ответ дан 29 November 2019 в 21:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: