Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> сделать strong_typedef ещё strong'ее 
V
    Опции темы
borisbn
Дата 21.11.2011, 09:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Всем привет.
Хотел сделать 2 типа таким образом, чтобы преобразование из одного в другой было бы невозможно, несмотря на то, что по сути эти типы одинаковые.
Сделал такой код:
Код

BOOST_STRONG_TYPEDEF( std::vector< unsigned char >, request_t )
BOOST_STRONG_TYPEDEF( std::vector< unsigned char >, response_t )

void foo1( const request_t & r ) {}
void foo2( const response_t & r ) {}

request_t r;
foo1( r );
foo2( r );

foo1 отрабатывает (как и должна), на foo2 ругается (как и должна).

Но затем сделал так:
Код
request_t r;
response_t r1;
r = r1;

и это - отрабатывает (хотя мне бы хотелось, чтобы выдавалась ошибка).

Эту тему - механизм "улучшенного" typedef - смотрел, но, как я понял, тогда решения не нашли (кроме mpl, которую не хочется тянуть ради такой задачи)

Спасибо.


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
boostcoder
Дата 21.11.2011, 09:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



во первых - для тех кто желает ознакомиться с макросом , он определен тут: http://gitorious.org/boost/svn/blobs/maste...ong_typedef.hpp
Код

    #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() : t(){};                                                \
        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; }   \
    };

в твоем примере, нежелательное поведение происходит из-за перегруженных operator type();
если их закомментировать, то все ок.

пример:
Код

#include <vector>
#include <boost/serialization/strong_typedef.hpp>

struct request_t : boost::totally_ordered1< request_t , boost::totally_ordered2< request_t, std::vector< unsigned char > > > {
   std::vector< unsigned char > t;

   explicit request_t(const std::vector< unsigned char > t_) : t(t_) {}
   request_t(){}
   request_t(const request_t & t_) : t(t_.t){}

   request_t & operator=(const request_t & rhs) { t = rhs.t; return *this;}
   request_t & operator=(const std::vector< unsigned char > & rhs) { t = rhs; return *this;}

//   operator const std::vector< unsigned char > & () const {return t; }
//   operator std::vector< unsigned char > & () { return t; }

   bool operator==(const request_t & rhs) const { return t == rhs.t; }
   bool operator<(const request_t & rhs) const { return t < rhs.t; }
};

struct response_t : boost::totally_ordered1< response_t , boost::totally_ordered2< response_t, std::vector< unsigned char > > > {
   std::vector< unsigned char > t;

   explicit response_t(const std::vector< unsigned char > t_) : t(t_) {}
   response_t(){}
   response_t(const response_t & t_) : t(t_.t){}

   response_t & operator=(const response_t & rhs) { t = rhs.t; return *this;}
   response_t & operator=(const std::vector< unsigned char > & rhs) { t = rhs; return *this;}

//   operator const std::vector< unsigned char > & () const {return t; }
//   operator std::vector< unsigned char > & () { return t; }

   bool operator==(const response_t & rhs) const { return t == rhs.t; }
   bool operator<(const response_t & rhs) const { return t < rhs.t; }
};

void foo1( const request_t & r ) {}
void foo2( const response_t & r ) {}

int main() {
   request_t req;
   response_t res, res2;

   req = res; // error
   foo1( req );
//   foo2( req );
}


http://liveworkspace.org/code/62d1803c53fc...125a31db9e76ecd

а вот почему(и как это исправить) operator type() дает такой эффект - это нужно у более компетентных полюбопытствовать.

Это сообщение отредактировал(а) boostcoder - 21.11.2011, 09:59
PM WWW   Вверх
math64
Дата 21.11.2011, 10:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Можно так:
Код

struct  T1 {
int x;
T1() : x (0) {}
T1(const T1&t) : x(t.x) {}
T1(int y) : x(y) {}
operator int() { return x; }
T1& operator=(int y) { x = y; return *this; }
};

struct  T2 {
int x;
T2() : x (0) {}
T2(const T2&t) : x(t.x) {}
T2(int y) : x(y) {}
operator int() { return x; }
T2& operator=(int y) { x = y; return *this; }
};

int f(T1&t1) { return t1.x; }
int f(T2&t2) { return t2.x; }
int main() {
T1 t1;
T2 t2;
t1 = t2;
}

В случае vector (и других классов) можно так:
Код

class request_t : public std::vector< unsigned char > { 
// определить нужные конструкторы
};
class response_t : public std::vector< unsigned char > { 
// определить нужные конструкторы
};


Это сообщение отредактировал(а) math64 - 21.11.2011, 10:09
PM   Вверх
boostcoder
Дата 21.11.2011, 10:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



еще два способа:
1. закоментить operator=() для "голого" типа.
2. указать для operator=() "голого" типа спецификатор =delete.


math64, ну почему вы так безобразно код пишите?
или вы не рассчитываете что его читать будут?


Добавлено через 4 минуты и 30 секунд
странный какой-то strong typedef получается..
PM WWW   Вверх
borisbn
Дата 21.11.2011, 10:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



мдааа. похоже BOOST_STRONG_TYPEDEF не получится использовать (даже убрав оператор приведения к T), т.к. не получится использовать так
Код
void foo1( request_t & r ) { r.push_back( 42 ); }

обычный typedef в этом плане предпочтительней, но он даёт привести что хочешь к чему хочешь...
на ИРКе посоветовали boost::units
ушёл курить юнитс'ы.

Добавлено @ 10:27
math64, в Вашем примере
Цитата(math64 @  21.11.2011,  10:07 Найти цитируемый пост)
T1 t1;
T2 t2;
t1 = t2;


не выдаётся ошибки, а мне нужно, чтобы выдавалась. Ведь T1 и T2 - разные типы.

Это сообщение отредактировал(а) borisbn - 21.11.2011, 10:28


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
boostcoder
Дата 21.11.2011, 11:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



я бы поступил так:
Код

#include <vector>
#include <boost/strong_typedef.hpp>

#define MY_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() : t(){};                                                \
    D(const D & t_) : t(t_.t){}                                 \
    D & operator=(const D & rhs) { t = rhs.t; return *this;}    \
    operator T & () { return t; }                               \
    bool operator==(const D & rhs) const { return t == rhs.t; } \
    bool operator<(const D & rhs) const { return t < rhs.t; }   \
};

MY_STRONG_TYPEDEF( std::vector< unsigned char >, request_t )
MY_STRONG_TYPEDEF( std::vector< unsigned char >, response_t )

void foo1( const request_t & r ) {}
void foo2( const response_t & r ) {}

int main() {
   request_t req;
   response_t res, res2;

   res = res2;
//   req = res; // error
   foo1( req );
//   foo2( req ); // error
}


т.е. удалил бы operator=() для T

Добавлено @ 11:41
Цитата(borisbn @  21.11.2011,  10:24 Найти цитируемый пост)
посоветовали boost::units

какой-то конкретный шаблон? или его еще и отрыть нужно? smile 

Это сообщение отредактировал(а) boostcoder - 21.11.2011, 12:21
PM WWW   Вверх
boostcoder
Дата 21.11.2011, 12:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(borisbn @  21.11.2011,  10:24 Найти цитируемый пост)

не получится использовать так

void foo1( request_t & r ) { r.push_back( 42 ); }

так в любом случае не получится. у request_t нет метода push_back()

PM WWW   Вверх
mes
Дата 21.11.2011, 13:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



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



Это сообщение отредактировал(а) mes - 21.11.2011, 15:36


--------------------
PM MAIL WWW   Вверх
borisbn
Дата 21.11.2011, 14:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(boostcoder @  21.11.2011,  12:11 Найти цитируемый пост)
так в любом случае не получится. у request_t нет метода push_back()

при обычном typedef'е есть

Цитата(mes @  21.11.2011,  13:09 Найти цитируемый пост)
если Вам нужно это для действительно для request и response,то не мучайте не себя не людей, а заведите по структуре на каждый

вообще-то я request и response привёл как пример. ведь существует ещё множество "типов", поведение которых выглядит в точности как vector< unsigned char >, но их нельзя (по логике) присваивать друг другу...
если бы typedef не давал возможности приведения (или его как-то можно было запретить), то он бы меня устраивал по-полной программе...
поэтому ж и начал 
Цитата(mes @  21.11.2011,  13:09 Найти цитируемый пост)
мучайте не себя не людей

 smile 


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
mes
Дата 21.11.2011, 15:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(borisbn @  21.11.2011,  13:54 Найти цитируемый пост)
 ведь существует ещё множество "типов", поведение которых выглядит в точности как vector< unsigned char >, но их нельзя (по логике) присваивать друг другу...

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

Добавлено через 3 минуты и 26 секунд
Цитата(borisbn @  21.11.2011,  13:54 Найти цитируемый пост)
мучайте не себя не людей

а где Выши любимые замечание по нарушению правил русского языка.. прочитал как я написал, волосы дыбом встали.. поправил smile 


Добавлено через 4 минуты и 45 секунд
Цитата(borisbn @  21.11.2011,  13:54 Найти цитируемый пост)
если бы typedef не давал возможности приведения

в С++ typedef и не является def type`ом smile отсюда и нужно плясать..

Добавлено через 6 минут
в общем для приведенного случая напрашивается максимум packet<request> и packet<response>..


Это сообщение отредактировал(а) mes - 21.11.2011, 15:28


--------------------
PM MAIL WWW   Вверх
borisbn
Дата 21.11.2011, 16:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(mes @  21.11.2011,  15:26 Найти цитируемый пост)
а где Выши любимые замечание по нарушению правил русского языка.. 

я решил, что макать гуру Си++ - себе дороже - отыграется на Си-плюс-плюсе smile

Цитата(mes @  21.11.2011,  15:26 Найти цитируемый пост)
в общем для приведенного случая напрашивается максимум packet<request> и packet<response>..

как это ?
я пробовал
Код

typedef std::vector< unsigned char > request_t;
typedef std::vector< unsigned char > response_t;

template < class T >
struct packet { T v; };

foo1 и foo2 вызываются с одним типом packet< request_t > без ошибок...


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
mes
Дата 21.11.2011, 17:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(borisbn @  21.11.2011,  15:16 Найти цитируемый пост)
template < class T >
struct packet { T v; };

 smile, так :
Код

template<typename T>
struct packet
{
   std::vector<char> v;
};

// так:
struct request_tag; // или может быть request_traits со всеми исходящими следствиями...
typedef packet<request_tag> request_packet_t; // или request_t

//или так:
typedef packet<struct response_tag> response_packet_t;// или response_t;

// ...
   response_packet_t s;
   request_packet_t q;
   
//   q = s; // error;




Цитата(borisbn @  21.11.2011,  15:16 Найти цитируемый пост)
макать гуру Си++

ну это вы загнули..


Это сообщение отредактировал(а) mes - 21.11.2011, 17:36


--------------------
PM MAIL WWW   Вверх
borisbn
Дата 21.11.2011, 18:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



получается, что без промежуточного .v не обойтись... жаль.
получается либо так
Код

struct request_t {
   std::vector<char> v;
};
struct response_t {
   std::vector<char> v;
};

либо как Вы написали (через шаблонный packet)...
склоняюсь к Вашему варианту...

Всем спасибо. Закрываю.


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
mes
Дата 21.11.2011, 19:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(borisbn @  21.11.2011,  17:10 Найти цитируемый пост)
получается, что без промежуточного .v не обойтись... жаль.

1. перегрузкой ->
2. определением полноценного интерфейса (рекомендуется)


--------------------
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0610 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.