Привести boost::shared_array‹char› к boost::shared_array‹const char›

Как я могу преобразовать boost::shared_array<char> в boost::shared_array<const char>?


person Joakim Karlsson    schedule 04.12.2009    source источник
comment
Как вы думаете, почему вам нужно это делать?   -  person    schedule 04.12.2009


Ответы (7)


Поскольку у shared_array нет метода add_ref, вы можете эмулировать его следующим образом:

struct MagicDeleter {
  MagicDeleter( boost::shared_array<char> ptr ) : ptr(ptr) {};
  template<typename T> void operator()(T*) {} 
protected:
  boost::shared_array<char> ptr;
};

...

boost::shared_array<char> orig_ptr( some_val );
boost::shared_array<const char> new_ptr( orig_ptr.get(), MagicDeleter(orig_ptr) );
person Kirill V. Lyadvinsky    schedule 04.12.2009

Другие ответы правильные, вы не можете и не должны.

Кроме того, вы уверены, что хотите boost::shared_array<const char>, а не const boost::shared_array<char>?

Практически это работает:

boost::shared_array<char> acz;
boost::shared_array<const char>& acz2 = reinterpret_cast< boost::shared_array<const char>& >(acz);

НО это не очень хорошая идея и работает только в том случае, если boost::shared_array и boost::shared_array имеют одинаковую реализацию. Шаблоны могут быть частично специализированными:

template<class T>
struct TwoImplementations {
    int m_nIntMember;
};

template<>
struct TwoImplementations< const T > {
    double m_fDoubleMember;
};

Выполнение повторного приведения между TwoImplementations<int> и TwoImplementations<const int> просто неправильно.

person Sebastian    schedule 04.12.2009
comment
Никогда не используйте такой reinterpret_cast, особенно в этом случае! Вообще говоря, reinterpret_cast на 99% не переносим. - person rmn; 04.12.2009
comment
Я знаю это и подтверждаю это в своем посте. Поэтому, пожалуйста, не минусуйте. Это особенность языка, она может работать и в 1% случаев даже может быть полезна. - person Sebastian; 04.12.2009
comment
@rmn: Один размер не подходит всем, я согласен, что в этом месте это плохая идея, но никогда не говори никогда. - person Joe D; 11.09.2010

Вы не можете.

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

person Frunsi    schedule 04.12.2009

Я думаю, ты не можешь. Однако, если вам это действительно нужно, вы можете создать собственный класс интеллектуальных указателей. Подсказки для этого можно найти здесь.

person Björn Pollex    schedule 04.12.2009

Вы можете использовать метод get() для получения базового char*, который автоматически преобразуется в const char*, но не назначайте его другому shared_array, потому что тогда данные будут удалены дважды. Просто используйте его по мере необходимости.

нравится:

boost::shared_array<char> x(new int[13]);
const char *y = x.get();
person rmn    schedule 04.12.2009

Я бы не подумал об этом без потрясающего ответа Кирилла, но вы можете эффективно расширить static_pointer_cast boost, который используется для shared_ptrs, для работы с shared_arrays следующим образом:

template<typename OriginalType>
struct SharedPtrCastHelper
{
  public:
    SharedPtrCastHelper( const OriginalType & ptr ) : ptr(ptr) {};
    template<typename T> void operator()(T*) {}

  protected:
    OriginalType ptr;
};


template<typename OutT, typename InT>
boost::shared_array<OutT> 
static_pointer_cast( const boost::shared_array<InT> & inSharedPtr )
{
  typedef SharedPtrCastHelper<boost::shared_array<InT> >  Helper;

  return boost::shared_array<OutT>( (OutT*)inSharedPtr.get(), 
                                    Helper(inSharedPtr) );
}

с этим вы можете сделать что-то вроде:

boost::shared_array<int>          intArrayPtr( new int[40] );  
boost::shared_array<unsigned int> uintArrayPtr;

uintArrayPtr = static_pointer_cast<unsigned int>( intArrayPtr );
person Catskul    schedule 22.07.2011

Такое приведение, сгенерированное компилятором, невозможно.

Внутреннее устройство класса с константным параметром шаблона может существенно отличаться от класса без него из-за особенности специализации шаблона.

Более того, использование такой функции иногда является фоном для проверок во время компиляции, которые просто могут не разрешить создание экземпляра типа A<const T> для каждого случая, когда тип A<T> является правильным.

person P Shved    schedule 04.12.2009
comment
Невозможно? Тем не менее, boost::shared_ptr поддерживает неявное преобразование производных типов в базовые (и неконстантных в константные) и всевозможные приведения типов. - person Alex B; 04.12.2009
comment
Он действительно поддерживает преобразование. Но его нельзя привести к типу. - person P Shved; 04.12.2009
comment
Он поддерживает приведения, если вы не имеете в виду что-то совсем другое. Например, boost::shared_ptr<Derived> ptr(boost::static_pointer_cast<Derived>(base_shared_ptr)); - person Alex B; 16.12.2009