Вы можете взять следующий подход в качестве отправной точки, в основном мне пришлось определить некоторые служебные методы:
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)
);
Нет, но это может фальсифицироваться в различных степенях с шаблонами:
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 mixins могут быть удовлетворены с помощью нескольких (виртуальное) наследование. К сожалению, это часто представляет больше проблем, чем это решает. Кроме того, Вы не можете суперклассы смешивания и подгонки на лету а-ля:
val me = new Human with Coder with Musician
Если Вы действительно, действительно хотите истинный mixins, почти необходимо пойти с чем-то как шаблонное решение, предложенное в ответе @Logan Capaldo.
Чтобы повторить и расширить то, что упоминалось в предыдущих письмах, позвольте мне сначала дать вам пример того, как реализовать черту 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.