Здравствуйте, enji, Вы писали:
E>Нельзя ли как-нибудь проще сделать?
Как вариант, можно сделать константность шаблонным параметром. Тем не менее, в Boost.Asio
схожие концепты реализованы полностью раздельно.
Здравствуйте, Chorkov, Вы писали:
C>Пусть константные/не константные методы класса, соотвсетуют константным/не константным методам обертки.
C>Изготавливать обертку двуия фабриками:
C>C>shared_ptr<Foo> make_foo(byte*);
C>shared_ptr<const Foo> make_foo(const byte*);
C>
C>Недостаток: закладываемся на определенную политику владения объектами.
Можем сделать другую политику
template<class T> class itself_ptr
{
mutable T data_;
public:
explicit itself_ptr(const T& src) : data_(src) {}
T* operator->() const { return const_cast<T*>(&data_); }
T& operator* () const { return const_cast<T&>( data_); }
};
здесь mutable и const_cast рассчитаны на то, что T — это обёртка, которую можно безболезненно копировать, как угодно.
Выбирая между itself_ptr<Wrapper> и itself_ptr<const Wrapper>, получаем желаемое.
Здравствуйте, Кодт, Вы писали:
К>Можем сделать другую политику
имхо и без const_cast все шоколадно
http://ideone.com/5MnRf
http://ideone.com/xfenR
Здравствуйте, uzhas, Вы писали:
К>>Можем сделать другую политику
U>имхо и без const_cast все шоколадно
да это я сперва наконсткастил, а потом про мутабле вспомнил
В общем, как я понял, самое прямое решение из предложенных вот такое:
template<class T> class itself_ptr
{
mutable T data_;
public:
explicit itself_ptr(const T& src) : data_(src) {}
T* operator->() const { return &data_; }
T& operator* () const { return data_; }
};
namespace detail {
struct TDBAddressImpl
{
static int long_getter(const byte *buf);
static void long_setter(byte *buf, double v);
};
}
template<class T>
class TDBAddress_
{
T *buf_;
public:
TDBAddress_(T *buf) : buf_(buf) {}
byte getter() const { return buf_[105]; }
void setter(byte v) { buf_[106] = v; }
int long_getter() const { return detail::TDBAddressImpl::long_getter(buf_); }
};
typedef itself_ptr<TDBAddress_<byte> > TDBAddress;
typedef itself_ptr<TDBAddress_<const byte> > TDBAddressConst;
inline TDBAddress make_dbaddress(byte *buf) { return TDBAddress(TDBAddress_<byte>(buf)); }
inline TDBAddressConst make_dbaddress(const byte *buf) { return TDBAddressConst(TDBAddress_<const byte>(buf)); }
Его плюсы — нет const_cast и дублирования методов.
Его минусы
— нужны дополнительные заморочки, чтобы можно было преобразовать TDBAddress в TDBAddressConst
— itself_ptr можно вынести в библиотеку (если таких оберток будет много), но все равно много мусора — тайпдефы, make_dbaddress, отдельный struct для тяжелых функций, реализацию которых не охота светить в хидере, переадресация вызовов для таких функций.
ИМХО, исходное решение, хотя и не слишком красиво смотрится, вполне имеет право на жизнь