6

How can I cast a boost::shared_array<char> to boost::shared_array<const char>?

Joakim Karlsson
  • 1,112
  • 1
  • 15
  • 27

7 Answers7

6

Since shared_array has no add_ref method you could emulate it as follows:

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) );
Kirill V. Lyadvinsky
  • 97,037
  • 24
  • 136
  • 212
3

The other answers are correct, you can't and you shouldn't.

Besides, are you sure you want a boost::shared_array<const char> and not a const boost::shared_array<char>?

Practically, this works:

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

BUT it is not a good idea and only works if boost::shared_array and boost::shared_array have the same implementation. Templates can be partially specialized:

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

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

Doing a reinterpret cast between TwoImplementations<int> and TwoImplementations<const int> is just wrong.

Sebastian
  • 4,802
  • 23
  • 48
  • 1
    Never use such a reinterpret_cast, especially in this case! Generally speaking, reinterpret_cast is 99% not portable. – rmn Dec 04 '09 at 12:45
  • I know that and acknowledge it in my post. So please don't downvote. It is a language feature, it can work and in 1% of the cases may even be useful. – Sebastian Dec 04 '09 at 12:46
  • @rmn: One size does not fit all, I agree that in this place it's a bad idea, but never say never. – Joe D Sep 10 '10 at 20:41
1

You can't.

As both types are based on a template, both types are completely different for the compiler.

Frunsi
  • 7,099
  • 5
  • 36
  • 42
1

I think you can't. In case you really need it though, you can create a custom smart-pointer class. Hints for that can be found here.

Community
  • 1
  • 1
Björn Pollex
  • 75,346
  • 28
  • 201
  • 283
1

You could use the get() method to get the underlying char*, which is auto convertible to a const char* - but don't assign it to another shared_array because then you'll have the data deleted twice. Just use it as you need it.

like this:

boost::shared_array<char> x(new int[13]);
const char *y = x.get();
rmn
  • 2,386
  • 1
  • 14
  • 21
1

I wouldn't have thought of this without Kirill's awesome answer, but you can effectively extend boost's static_pointer_cast that is used for shared_ptrs to work on shared_arrays as so:

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) );
}

with that you can then do something like:

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

uintArrayPtr = static_pointer_cast<unsigned int>( intArrayPtr );
Catskul
  • 17,916
  • 15
  • 84
  • 113
0

Such compiler-generated casting can not be possible.

The internals of the class with const-qualified template parameter may differ dramatically from the class without one, due to template specialization feature.

Moreover, the use of such feature is sometimes a background for compile-time checks that merely may not allow instantiation of A<const T> type for every case where A<T> type is correct.

P Shved
  • 96,026
  • 17
  • 121
  • 165
  • 1
    Not possible? Yet boost::shared_ptr supports implicit conversion from derived to base types (and non-const to const) and all sorts of casts. – Alex B Dec 04 '09 at 12:46
  • It indeed does support *conversion*. But it can't be *type-casted*. – P Shved Dec 04 '09 at 13:09
  • It does support casts, unless you mean something else entirely. E.g., `boost::shared_ptr ptr(boost::static_pointer_cast(base_shared_ptr));` – Alex B Dec 16 '09 at 02:06