Инкапсулируйте простой тип, используя шаблоны C ++ - PullRequest
2 голосов
/ 12 февраля 2009

Я хочу добавить функциональность ко всем простым типам в C ++.

Я хочу написать один шаблонный класс, который принимает в качестве параметра шаблона тип для инкапсуляции, а затем определяет все операторы, так что инкапсулированный класс работает точно так же, как простой тип, который он инкапсулирует.

Примерно так:

template <typename _SimpleType_>
class Attribute
{
public:
    Attribute(_SimpleType_ value){ m_value = value; }
    ~Attribute(){}

    // Cast
    operator _SimpleType_() { return(m_value); }

    // Comparisons
    bool operator==(const a& other) const { return a == m_value; }
    etc...

private:
   _SimpleType_ m_value;
}

// Use like:
Attribute<int> i = 20;

while(i)
{
   if((i & 0xF) == 0)
   {
      i >>= 2;
   }

   i--;
}  etc...

Вопрос в том, что я уверен, что есть масса нюансов, с которыми нужно разобраться, и написаны специализированные операторы шаблонов; Так есть ли где-нибудь, что это уже было сделано, чтобы я мог использовать это вместо этого?

Boost слишком большой и сложный для размещения в моем проекте, но я могу посмотреть на него для указателей, если там есть такой класс - как он называется, если есть?

Ответы [ 6 ]

4 голосов
/ 12 февраля 2009

Это довольно просто, если утомительно, - вам просто нужно реализовать все операторы, поддерживаемые стандартными типами, и там, где оператор приведения не достаточен.

Я должен спросить, почему, с какой стати вы пытаетесь это сделать?

2 голосов
/ 12 февраля 2009

Вот пример использования автоматической трансляции типов для T & (протестировано с GNU C ++ 4.3.2):

#include <iostream>

using namespace std;

template <typename T>
class Attribute {
public:
    Attribute(const T &value) { v = value; }
    operator T & () { return v; }
private:
    T v;
};

int main(int argc, char **argv)
{
    Attribute<int> i(0);
    i = 3;
    i++;
    i += 4;
    i = i + 5;
    i <<= 3;
    cout << "i is now " << i << endl;
}

Компилятор C ++ автоматически преобразует ссылку на «Атрибут» в ссылку на «int» с помощью оператора приведения «оператор T & ()». Поэтому, когда класс Attribute не предоставляет оператора '++' или чего-либо еще, объект типизируется в int &, а затем оператор ищется оттуда. Не стесняйтесь экспериментировать.

2 голосов
/ 12 февраля 2009

Вы можете получить реализацию немутирующих операторов бесплатно, просто преобразовав в _Simple_type_ (и получите преобразования и увеличение / уменьшение при преобразовании в _Simple_type_&). Другой вопрос: действительно ли это хорошая идея, поскольку она создает преобразования как T в Attribute<T>, так и Attribute<T> в T, что вызывает проблемы при перегрузке - но это можно исправить, сделав конструктор Attribute<T> явный.

Это оставляет присваивания и увеличение / уменьшение - вам просто нужно их реализовать.

Другая возможность заключается в использовании boost::operators - библиотеки только для заголовков, которая облегчает создание перегрузок операторов на основе алгебраических правил. например. вы создаете operator+=, и он предоставит вам operator+. Вы создаете operator< и operator==, и это даст вам другие отношения и т. Д.

1 голос
/ 12 февраля 2009

Не относится к вашему вопросу, но вы должны знать, что такие имена, как _SimpleType_ (то есть имена, начинающиеся с символа подчеркивания и заглавных букв), зарезервированы для использования компилятором C ++ и разработчиками Standard Libarary - Вы не можете использовать их в своем собственном коде.

0 голосов
/ 11 марта 2009

Мне нравится эта форма инкапсуляции простых типов ( оригинальный автор - Sektor van Skijlen ):

template<typename T>
class explicit_t
{
private:
    T value;

    template<typename V> explicit_t(V t);
public:
    operator T&() {return value;}
    explicit_t(const T& c) : value(c) {}    
}; 

И короткий пример:

void fun(explicit_t<int> foo) {}

int main()
{
        // fun('a');
        // fun(3u);
        // fun(3.0);
        fun(4);
}

Так что я получу? Нет больше нежелательных конверсий.

Возможно, вы захотите взглянуть на что-то более причудливое - typegen .

0 голосов
/ 12 февраля 2009

Я не уверен, что boost::ref - это то, что вы ищете.

В любом случае, лучшее, что вы должны сделать, это просто написать это вручную - но это станет проблемой, если вы намерены поддерживать семантику указателей и ссылок.

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

...