2013-05-22 2 views
4

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

typedef MyBigIntegerClass bigInt; 
typedef int smallInt; 

Коммуникационная часть не совместима с MyBigIntegerClass, поэтому перед сообщением, например, вектор bigInts он должен быть преобразован в smallints. Пока что проблем нет.

Однако для большинства проблемных случаев использование MyBigIntegerClass не требуется. На самом деле достаточно даже int32_t. Вот почему я допускаю такую ​​конфигурацию, как

typedef int32_t bigInt; 
typedef int16_t smallInt; 

Тип bigInt по-прежнему достаточно велик для вычислительных материалов. Проблема заключается в том, что smallInt должен отличаться от bigInt.

class Problematic 
{ 
    public: 
     Problematic(bigInt); 
     Problematic(smallInt); 
}; 

В этом классе конструкторы или методы могут либо принимать значения bigInts, либо smallInts. Если они совпадают, компиляция не выполняется.

Поскольку другие пользователи кода, возможно, захотите настроить используемые типы, они могут в конечном итоге с конфигурацией, такие как

typedef int32_t bigInt; 
typedef int32_t smallInt; 

и компиляции терпит неудачу в (по крайней мере, некоторых разработчиков) неочевидным способом ,

Один из способов иметь дело с static_assert(sizeof(bigInt) != sizeof(smallint), "bad config.."), но мне действительно нравится возможность иметь bigInt == smallInt. Что было бы хорошим способом изменить объявление class Problematic, чтобы разрешить эквивалентность типов?

ответ

2

Если желательно сохранить как Конструкторы возможное решение обернуть int типа в шаблонах означает, что они разные типы всегда, даже если основной int типа тот же:

template <typename T> 
struct big_int 
{ 
    T value; 
}; 

template <typename T> 
struct small_int 
{ 
    T value; 
}; 

typedef big_int<long> bigInt; 
typedef small_int<long> smallInt; 

class Problematic 
{ 
public: 
    Problematic(bigInt) {} 
    Problematic(smallInt) {} 
}; 

компилировать, когда базовые типы те же (http://ideone.com/KGz9Vk) и когда они не совпадают (http://ideone.com/Pt0XGS).

Чтобы позволить big_int<> и small_int<> вести себя как интегральные типы, требуются реализации операторов. Например:

template <typename T> 
struct big_int 
{ 
    T value; 
    operator T() { return value; } 

    big_int& operator+=(big_int const& other) 
    { 
     value += other.value; 
     return *this; 
    } 

    template <typename U> 
    big_int& operator+=(U const& v) 
    { 
     value += v; 
     return *this; 
    } 

    big_int& operator++() 
    { 
     ++value; 
     return *this; 
    } 

    big_int operator++(int) 
    { 
     big_int temp = *this; 
     ++value; 
     return temp; 
    } 
}; 

Это не является исчерпывающим (см http://herbsutter.com/2013/05/20/gotw-4-class-mechanics/ за полезные рекомендации по осуществлению операторов). См. Например, http://ideone.com/xlE2Mi.

+0

Это, безусловно, хороший способ провести различие между типами. Однако, похоже, он нарушает обычный интерфейс (например, сравнение с целыми числами). Любая идея о том, как избежать этого, не переопределяя весь интерфейс в 'template struct small_int'? – stefan

+0

@stefan, для сравнения с целыми числами, добавляет оператор преобразования в оператор 'template's:' T() {возвращаемое значение; } '. – hmjd

+0

Да, но это не очень красиво, так как мне также нужна потоковая передача, присваивание. – stefan

Смежные вопросы