Как организовать неприводимые друг к другу целочисленные типы?
От: _hum_ Беларусь  
Дата: 02.08.14 17:03
Оценка:
Как проще всего организовать два неприводимых неявно друг к другу целочисленных типа.
То есть, хочется чтобы компилятор автоматически отслеживал ошибки наподобие:


// <какое-то объявление неприводимых друг к другу целочисленных типов type_1, type_2>

void f(type_1 _x)
{
  //<bla-bla>
}

void main()
{
   type_1  x;
   type_2  u;

   x = u; //должен выдать ошибку
   f(u);  //должен выдать ошибку
};


Спасибо.
Re: Как организовать неприводимые друг к другу целочисленные типы?
От: swingus  
Дата: 02.08.14 18:08
Оценка:
BOOST_STRONG_TYPEDEF()

Здравствуйте, _hum_, Вы писали:

__>Как проще всего организовать два неприводимых неявно друг к другу целочисленных типа.

__>То есть, хочется чтобы компилятор автоматически отслеживал ошибки наподобие:
Re[2]: Как организовать неприводимые друг к другу целочисленные типы?
От: _hum_ Беларусь  
Дата: 02.08.14 19:05
Оценка:
Здравствуйте, swingus, Вы писали:

S>BOOST_STRONG_TYPEDEF()


S>Здравствуйте, _hum_, Вы писали:


__>>Как проще всего организовать два неприводимых неявно друг к другу целочисленных типа.

__>>То есть, хочется чтобы компилятор автоматически отслеживал ошибки наподобие:


а без буста никак? во-первых, не хочется сторонние библиотеки,а во-вторых, хочется простоты и прозрачности кода.
Re: Как организовать неприводимые друг к другу целочисленные типы?
От: Erop Россия  
Дата: 02.08.14 19:51
Оценка:
Здравствуйте, _hum_, Вы писали:

__>Как проще всего организовать два неприводимых неявно друг к другу целочисленных типа.

оно
Автор: Erop
Дата: 29.04.08
?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Как организовать неприводимые друг к другу целочисленные типы?
От: denisko http://sdeniskos.blogspot.com/
Дата: 03.08.14 09:50
Оценка:
Здравствуйте, _hum_, Вы писали:

http://en.cppreference.com/w/cpp/language/user_literal
<Подпись удалена модератором>
Re[3]: Как организовать неприводимые друг к другу целочисленные типы?
От: jazzer Россия Skype: enerjazzer
Дата: 03.08.14 09:54
Оценка:
Здравствуйте, _hum_, Вы писали:

S>>BOOST_STRONG_TYPEDEF()


__>а без буста никак? во-первых, не хочется сторонние библиотеки,а во-вторых, хочется простоты и прозрачности кода.


Ну скопируй конкретно это из буста, оно маленькое, особенно если тебе не нужно кучу разных компиляторов поддерживать.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[4]: Как организовать неприводимые друг к другу целочисленные типы?
От: _hum_ Беларусь  
Дата: 03.08.14 11:58
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, _hum_, Вы писали:


__>>Как проще всего организовать два неприводимых неявно друг к другу целочисленных типа.

E>оно
Автор: Erop
Дата: 29.04.08
?


Нет. Там все же про другое речь.

Здравствуйте, denisko, Вы писали:

D>Здравствуйте, _hum_, Вы писали:


D>http://en.cppreference.com/w/cpp/language/user_literal


Не совсем понимаю вашу идею использования литералов для моей проблемы. Можете пояснить?

Здравствуйте, jazzer, Вы писали:

J>Здравствуйте, _hum_, Вы писали:


S>>>BOOST_STRONG_TYPEDEF()


__>>а без буста никак? во-первых, не хочется сторонние библиотеки,а во-вторых, хочется простоты и прозрачности кода.


J>Ну скопируй конкретно это из буста, оно маленькое, особенно если тебе не нужно кучу разных компиляторов поддерживать.


Во-первых, оно не маленькое, ибо ссылается и на другие бустовские вещи типа boost::totally_ordered1,
#include <boost/config.hpp>
#include <boost/operators.hpp>

#if !defined(__BORLANDC__) || __BORLANDC__ >= 0x590
    #define BOOST_STRONG_TYPEDEF(T, D)                              \
    struct D                                                        \
        : boost::totally_ordered1< D                                \
        , boost::totally_ordered2< D, T                             \
        > >                                                         \
    {                                                               \
        T t;                                                        \
        explicit D(const T t_) : t(t_) {};                          \
        D(){};                                                      \
        D(const D & t_) : t(t_.t){}                                 \
        D & operator=(const D & rhs) { t = rhs.t; return *this;}    \
        D & operator=(const T & rhs) { t = rhs; return *this;}      \
        operator const T & () const {return t; }                    \
        operator T & () { return t; }                               \
        bool operator==(const D & rhs) const { return t == rhs.t; } \
        bool operator<(const D & rhs) const { return t < rhs.t; }   \
    };
#else
    #define BOOST_STRONG_TYPEDEF(T, D)                              \
    struct D                                                        \
        : boost::totally_ordered1< D                                \
        , boost::totally_ordered2< D, T                             \
        > >                                                         \
    {                                                               \
        T t;                                                        \
        explicit D(const T t_) : t(t_) {};                          \
        D(){};                                                      \
        D(const D & t_) : t(t_.t){}                                 \
        D & operator=(const D & rhs) { t = rhs.t; return *this;}    \
        D & operator=(const T & rhs) { t = rhs; return *this;}      \
        /*operator const T & () const {return t; }*/                \
        operator T & () { return t; }                               \
        bool operator==(const D & rhs) const { return t == rhs.t; } \
        bool operator<(const D & rhs) const { return t < rhs.t; }   \
    };
#endif // !defined(__BORLANDC) || __BORLANDC__ >= 0x590

#endif // BOOST_STRONG_TYPEDEF_HPP

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

template<typename IntegerType, int uid>
class strong_redefined
{
    static const int s_uid;

    IntegerType m_val;
public:
               strong_redefined(IntegerType val = 0):m_val(val){}
    explicit   strong_redefined(const strong_redefined& X):m_val(X.m_val){}
               strong_redefined&  operator=(const strong_redefined& X){if(this != &X){m_val = X.m_val;}; return *this;}
    
    operator IntegerType()const{return m_val;}

    strong_redefined& operator+(IntegerType i){m_val += i; return *this;}
    //....
    //<остальные операторы для типа IntegerType > 
    //....
};

template<typename IntegerType, int uid>
int strong_redefined<IntegerType, uid>::s_uid = uid;





int _tmain(int argc, _TCHAR* argv[])
{
    typedef strong_redefined<int,1> type_1;
    typedef strong_redefined<int,2> type_2;

    
    type_1 x = 10;
    type_2 u = 20;

    type_1 y = 15;

    x = u;// ошибка компиляции
    x = y;// ок
 

    return 0;
}



Но, блин, надо тогда переопределять все операции (


Странно, почему в новом стандарте сделали строгие enum-ы, а строгих определений хотя бы для базовых типов — обошли стороной...
Re[4]: Как организовать неприводимые друг к другу целочисленные типы?
От: _hum_ Беларусь  
Дата: 03.08.14 12:47
Оценка:
Хотя, по идее, можно же и просто:

#define STRONG_INTTYPEDEF(IT, T)                  \
class T                                           \
{                                                 \
   IT m_v;                                        \
public:                                           \
 explicit  T(IT v = 0):m_v(v){}                   \
                                                  \
operator IT()const{return m_v;}                   \
T& operator+(const IT i){m_v += i; return *this;} \
T& operator-(const IT i){m_v -= i; return *this;} \
T& operator*(const IT i){m_v *= i; return *this;} \
T& operator/(const IT i){m_v /= i; return *this;} \
T& operator%(const IT i){m_v %= i; return *this;} \
T& operator++(void){++m_v; return *this;}         \
T& operator--(void){--m_v; return *this;}         \
bool operator<(const IT i){return (m_v < i);}     \
bool operator>(const IT i){return (m_v > i);}     \
bool operator<=(const IT i){return (m_v <= i);}   \
bool operator>=(const IT i){return (m_v >= i);}   \
bool operator==(const IT i){return (m_v == i);}   \
};                            


int _tmain(int argc, _TCHAR* argv[])
{
    STRONG_INTTYPEDEF(int, type_1);
    STRONG_INTTYPEDEF(int, type_2);

    
    type_1 x(10);
    type_2 u(20);

        type_1 y(15);

    //x = u;// ошибка компиляции
    x = y;// ок

    return 0;
}


Ведь так? Я не заблуждаюсь?
Re: Как организовать неприводимые друг к другу целочисленные типы?
От: slava_phirsov Россия  
Дата: 04.08.14 09:52
Оценка:
Здравствуйте, _hum_, Вы писали:

__>Как проще всего организовать два неприводимых неявно друг к другу целочисленных типа.



Если не хочется бюста и overhead-а на классы, то даю вредный совет:

enum intfoo {Foo0 = 0, FooMax = 65535};
enum intbar {Bar0 = 0, BarMax = 65535};


В ассемблерном коде все это все равно будет пожато до операций со встроенным int — никаких там конструкторов, деструкторов и прочей мутотени.

Осталось всего лишь: определить для intfoo|intbar operator+, operator++, operator-, operator--, ... Плюс понять, а как проводить неявное приведение int к intfoo|intbar и обратно (вы-таки будете смеяться, но не получится определить, например, operator int(intfoo) или operator intfoo(int)).
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re[2]: Как организовать неприводимые друг к другу целочисленные типы?
От: _hum_ Беларусь  
Дата: 04.08.14 11:13
Оценка:
Здравствуйте, slava_phirsov, Вы писали:

_>Здравствуйте, _hum_, Вы писали:


__>>Как проще всего организовать два неприводимых неявно друг к другу целочисленных типа.



_>Если не хочется бюста и overhead-а на классы, то даю вредный совет:


_>
_>enum intfoo {Foo0 = 0, FooMax = 65535};
_>enum intbar {Bar0 = 0, BarMax = 65535};
_>


_>В ассемблерном коде все это все равно будет пожато до операций со встроенным int — никаких там конструкторов, деструкторов и прочей мутотени.


_>Осталось всего лишь: определить для intfoo|intbar operator+, operator++, operator-, operator--, ... Плюс понять, а как проводить неявное приведение int к intfoo|intbar и обратно (вы-таки будете смеяться, но не получится определить, например, operator int(intfoo) или operator intfoo(int)).


Брр.. Может, я чего-то не знаю, но объявленные вами типы содержать только два значения (а не отрезки значений от Foo0 до FooMax и от Bar0 до BarMax).
Re[3]: Как организовать неприводимые друг к другу целочисленные типы?
От: slava_phirsov Россия  
Дата: 04.08.14 16:33
Оценка:
Здравствуйте, _hum_, Вы писали:

__>Брр.. Может, я чего-то не знаю, но объявленные вами типы содержать только два значения (а не отрезки значений от Foo0 до FooMax и от Bar0 до BarMax).


По стандарту любое целочисленное значение в диапазоне от минимального до максимального значений членов перечисления может быть приведено к типу перечисления и обратно без искажения, не?
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re[4]: Как организовать неприводимые друг к другу целочисленные типы?
От: _hum_ Беларусь  
Дата: 04.08.14 21:55
Оценка:
Здравствуйте, slava_phirsov, Вы писали:

_>Здравствуйте, _hum_, Вы писали:


__>>Брр.. Может, я чего-то не знаю, но объявленные вами типы содержать только два значения (а не отрезки значений от Foo0 до FooMax и от Bar0 до BarMax).


_>По стандарту любое целочисленное значение в диапазоне от минимального до максимального значений членов перечисления может быть приведено к типу перечисления и обратно без искажения, не?


enum intfoo {Foo0 = 0, FooMax = 65535};

intfoo x = (intfoo)(100);//некорректно, хоть и компилируется
Re[5]: Как организовать неприводимые друг к другу целочисленные типы?
От: Erop Россия  
Дата: 05.08.14 00:04
Оценка:
Здравствуйте, _hum_, Вы писали:

E>>оно
Автор: Erop
Дата: 29.04.08
?


__>Нет. Там все же про другое речь.


Можно же добавить ещё один параметр:
template<int TMinVal, int TMaxVal, typename Tag = void>
struct IntRange {//... дальше всё так же


Тогда
struct tag1 : IntRange<INT_MIN, INT_MAX, tag1>{ };
struct tag2 : IntRange<INT_MIN, INT_MAX, tag2>{ };

auto x = tag1::To( 10 );
auto y = tah2::To( 20 );
// x и y -- разные целые...
}


__>По идее, должно быть что-то наподобие


//...

__>Но, блин, надо тогда переопределять все операции (


Я, собственно, показал тебе как переопределять автоматом + это будет честный встроенный интегральный тип, а не класс...
+ ещё можно любой диапазон значений назначить


Тут так движок форума устроен, что лучше отвечать а каждое сообщение отдельно.
Во-первых, дерево
Во-вторых, тот, кому ответишь, может получить уведомление и ответить тебе дальше.
Я случайно заметил, что ты прочитал мой совет, например
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Как организовать неприводимые друг к другу целочисленные типы?
От: slava_phirsov Россия  
Дата: 05.08.14 08:15
Оценка:
Здравствуйте, _hum_, Вы писали:

__>enum intfoo {Foo0 = 0, FooMax = 65535};


__>intfoo x = (intfoo)(100);//некорректно, хоть и компилируется



"Против лома нет приема"(с) Приведение в стиле C позволяет приводит что угодно к чему угодно. Почти.
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re[6]: Как организовать неприводимые друг к другу целочисленные типы?
От: slava_phirsov Россия  
Дата: 05.08.14 08:40
Оценка:
Здравствуйте, slava_phirsov, Вы писали:

__>>intfoo x = (intfoo)(100);//некорректно, хоть и компилируется



Ненамногим сложнее:

class IntegralFoo
{
    // ... блекджек с ООП
};

IntegralFoo foo = *(IntegralFoo*)(100); // не было слышно ни вскрика, ни стона ...



Что еще раз доказывает: помешать программисту проращивать сквозь себя бамбук C++ не в состоянии — он не для того задумывался. "Хотите персональные ремни безопасности — используйте Ada" (c) Скотт Майерс
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re[5]: Как организовать неприводимые друг к другу целочисленные типы?
От: Erop Россия  
Дата: 05.08.14 13:40
Оценка:
Здравствуйте, _hum_, Вы писали:

__>enum intfoo {Foo0 = 0, FooMax = 65535};


__>intfoo x = (intfoo)(100);//некорректно, хоть и компилируется


А почему некорректно? Стандарт же гарантирует, что лежаший под перечислением интегральный тип вмещает весь диапазон?
Только лучше static_cast использовать.

Вообще, объявляя перечисление в С++ ты же объявляешь литералы, а не значения. Значения -- числа, только типизированные.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Как организовать неприводимые друг к другу целочисленные типы?
От: DmitryShm Россия  
Дата: 07.08.14 19:14
Оценка:
Здравствуйте, _hum_, Вы писали:

__>Как проще всего организовать два неприводимых неявно друг к другу целочисленных типа.


На ум приходят 2 идеи. Списки иницииализации С++ не позволяют сужения типов.

char x{12}; // нормально
char y{123456}; // ошибка компиляции



И еще Страуструп как-то на одной конференции по С++ говорил про работу с константами, имеющими размерности. Что-то типа
const mass_t a = 1kg;
assert(1000g == a); // без ошибок
const distance_t b = 1cm;
std::cout << a + b; // ошибка компиляции


Думаю нормальным плюсовым подходом будет работа с разными типами, т.к. если воздействовать на существующие целочисленные типы какими-то операторами, то это может негативно сказаться на уже работающем коде.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.