PengYu.UT@gmail.com wrote:[color=blue]
> In the following program, I want an iterator contain pointer pointing
> to constant object not const pointer. If it is possible would you
> please let me know how to do it?
>
> #include <boost/shared_ptr.hpp>
> #include <vector>
> #include <iterator>
> #include <iostream>
>
> class trial {
> public:
> void const_fun() const {
> std::cout << __PRETTY_FUNCTION__ << std::endl;
> }
> void non_const_fun() {
> std::cout << __PRETTY_FUNCTION__ << std::endl;
> }
> };
>
> int main(){
> std::vector<boost::shared_ptr<trial> > v;
> v.push_back(boost::shared_ptr<trial>(new trial));
> {
> std::vector<boost::shared_ptr<trial> >::iterator it = v.begin();
> (*it)->const_fun();
> (*it)->non_const_fun();
> }
> {
> std::vector<boost::shared_ptr<trial> >::const_iterator it =
> v.begin();
> (*it)->const_fun();
> (*it)->non_const_fun();//want a const trial, this function should
> not be called.
> }
> {
> std::vector<boost::shared_ptr<const trial> >::iterator it =
> v.begin();//compile error
> (*it)->const_fun();
> (*it)->non_const_fun();
> }
>
> std::vector<boost::shared_ptr<const trial> > v_const = v;//error,
> //is there any conversion of
> this kind?
>
> return EXIT_SUCCESS;
> }[/color]
There have been several debates on the Boost development group about
whether or not to give smart pointers "deep constness" (see for
instance
http://thread.gmane.org/gmane.comp.l...t.devel/95836).
This issue is particularly important when considering const member
functions that can change the pointees of its class' const members. For
instance,
class Foo
{
int *pi_;
std::vector<int> vi_;
public:
// ...
void Bar() const
{
pi_[0] = 0; // Ok, but unintended?
vi_[0] = 0; // Error! vi_ is const here
}
};
Boost smart pointers, like raw pointers, allow modification of the
pointees, but some standard containers like std::vector don't. Because
the goal for boost::shared_ptr was to be "as close as possible to a raw
pointer, but no closer", the final decision was to make it not support
deep constness.
To change the behavior of a smart pointer for members, you might use a
wrapper class like this:
template <typename T>
class deep_shared_ptr
{
public:
// Constructors
deep_shared_ptr() {}
template<typename Y>
deep_shared_ptr( Y* const y ) : m_ptr( y ) {}
template<typename Y>
deep_shared_ptr( boost::shared_ptr<Y>& that ) : m_ptr( that ) {}
template<typename Y>
deep_shared_ptr( deep_shared_ptr<Y>& that ) : m_ptr( that ) {}
// The usual operations
T* operator->() { return m_ptr.operator->(); }
T& operator*() { return m_ptr.operator*(); }
// The unusual: make pointee const if pointer is const
T const* operator->() const { return m_ptr.operator->(); }
T const& operator*() const { return m_ptr.operator*(); }
// Reset pass-throughs
template<typename Y>
void reset( Y* const y )
{ m_ptr.reset( y ); }
template<typename Y>
void reset( boost::shared_ptr<Y>& that )
{ m_ptr.reset( that ); }
template<typename Y>
void reset( deep_shared_ptr<Y>& that )
{ m_ptr.reset( that.Get() ); }
private:
boost::shared_ptr<T> m_ptr;
// Disable copying from const deep pointers
deep_shared_ptr( const deep_shared_ptr& );
deep_shared_ptr( const boost::shared_ptr<T>& );
template<typename Y>
deep_shared_ptr& operator=( const deep_shared_ptr<Y>& );
template<typename Y>
deep_shared_ptr& operator=( const boost::shared_ptr<Y>& );
};
Unfortunately, as is reflected in the disabled functions, deep pointers
of this kind do not support normal copy semantics since they don't
accept a copy from a const deep_shared_ptr and can thus cannot be used
in standard containers. They can be handy as members, however.
Cheers! --M