Классы-оболочки для примитивных типов данных

При разработке решения иногда может быть удобно предоставить классы-оболочки для примитивных типов данных. Рассмотрим класс, представляющий числовое значение, будь то double , float или int .

class Number {
private:
    double val;

public:
    Number(int n) : val(n) { }
    Number(float n) : val(n) { }
    Number(double n) : val(n) { }

    // Assume copy constructors and assignment operators exist

    Number& add(const Number& other) {
        val += other.val;
        return *this;
    }

    int to_int() const { return (int) val; }
    float to_float() const { return (float) val; }
    double to_double() const { return val; }
};

Теперь предположим, что у меня есть функция как таковая:

void advanced_increment(Number& n) {
    n.add(1);
}

И я бы использовал эту функцию как таковую:

Number n(2);
advanced_increment(n); // n = 3

Это звучит достаточно просто. Но что, если бы функция была такой?

void primitive_increment(int& n) {
    ++n;
}

Обратите внимание, что приращение является примером. Предполагается, что функция будет выполнять более сложные операции с примитивными типами данных, которые они также должны иметь возможность выполнять с типами Number без каких-либо проблем.

Как мне использовать эту функцию точно так же, как раньше? Пример:

Number n(2);
primitive_increment(n);

Как мне сделать мой класс Number совместимым с primitive_increment ? Как я могу создать класс-оболочку для примитивных типов данных, который был бы совместим везде, где требуются эти типы данных?

На данный момент я нашел только два решения. Один из них - создать такую ​​функцию, как double & Number :: get_value () , а затем использовать ее как primitive_increment (n.get_value ()); . Второе решение - создать методы неявного преобразования, такие как Number :: operator int & () ; но это может привести к множеству неоднозначных вызовов и запутать код.

Мне интересно, есть ли другое решение для реализации этих типов оболочек и сохранения их примитивной функциональности.

Обновление:

Для дальнейшего пояснения, в реальном проекте намерение состоит в том, чтобы сделать все типы данных производными от одного базового класса, который обычно упоминается как Объект при разработке такого решения. Ограничение заключается в том, что нельзя использовать внешнюю библиотеку. Следовательно, если у меня есть контейнер с указателями на тип Object , он должен иметь возможность хранить любое произвольное значение, примитивное или нет, и выполнять любые примитивные операции, разрешенные для Object ]. Надеюсь, это лучше объясняет.

6
задан Zeenobit 9 November 2011 в 00:59
поделиться