jbat100
jbat100

Reputation: 16827

C++ smart pointers with no std library

I'm a long time user of the boost::smart_ptr library and love it. Like all boost libraries it is design to work well with the C++ Standard Library. Which usually is a great thing.

Unfortunately, I'm facing a situation were I need to be completely independent of the standard library. Despite this I would need the same kind of functionality as that offered by the boost::smart_ptr (except, obviously every thing that has to do with std::). This includes amongst others, retain count, overloading of the bool and -> operators, relationships between week_ptr and shared_ptr etc.

Has anyone been faced with this situation? I'm looking into using the boost::smart_ptr as a starting point and replacing/eliminating std:: related things. But looking at the complexity, am increasingly concerned about breaking things.

Upvotes: 1

Views: 335

Answers (3)

reder
reder

Reputation: 1108

A classical in reference counting. Some basic code would look like this (shortest code I have managed to produce). Should be straightforward unless you know nothing about reference counting.

template <class CL>
struct refCount  {
    refCount() : nlinks_(1) , p_(0) {}
    refCount(CL*p) : nlinks_(1) , p_(p) {}
    ~refCount() { if (!nlinks_) delete p_;}
    size_t nlinks_;
    CL* p_;
    };

template <class CL>
class mySmartPtr {
public:
    mySmartPtr() : rc_(new refCount<CL>()) {}
    mySmartPtr(CL* p) : rc_(new refCount<CL>(p)) {}
    mySmartPtr(const mySmartPtr<CL> & otherSmartPtr) : rc_(otherSmartPtr.rc_) { rc_->nlinks_++ ;}
    mySmartPtr & operator=(const mySmartPtr<CL> & otherSmartPtr)        {
        otherSmartPtr.rc_->nlinks_++;
        if (!(-- rc_->nlinks_))  delete rc_;
        rc_ = otherSmartPtr.rc_; 
        return *this;}
    CL& operator *() {return * rc_->p_ ; }
    ~mySmartPtr() { if(!(--rc_->nlinks_)) delete rc_;}
// commented to print #links  (remove it)
// protected:
    refCount<CL> *rc_;
        };

A little (big) more work is needed if you need dynamic/static casts (thread safety).

Example of use:

int main()
{
 mySmartPtr<int> i;
 i = mySmartPtr<int>(new int(1));
 *i = 7;
 mySmartPtr<int> j(new int(3));
 j = i;
 std::cout << *j << std::endl ; // prints 7
 std::cout << i.rc_->nlinks_ << std::endl ; // prints 2, i and j point to the same
 {
  mySmartPtr<int> k(j);
  std::cout << i.rc_->nlinks_ << std::endl ; // prints 3, k points there two
 }
 std::cout << i.rc_->nlinks_ << std::endl ; // prints 2 , k gone out of scope

 return 0;
}

Upvotes: 0

Matthieu M.
Matthieu M.

Reputation: 300129

You might be interested in libc++.

This is an implementation of the C++ Standard Library with a liberal license (MIT or BSD-like) so that you can freely pick stuff out of it.

All the stream handling is very complicated (lot of locale stuff), however the STL part (containers and algorithms) as well as part of the numeric stuff (apart from formatting) could work out of the box.

If you need streams, it's a little more involved.

Finally, your biggest issue might come from the exception handling. Note that the Standard Library is normally supposed to work with exceptions enabled (std::out_of_range for example), and exception management is generally based on an external library (for example, see libunwind). Of course, since you reimplement your own library, you can choose to assert instead of throwing.

I would seriously advise not using exceptions as it will be a major pain to make it work on all the devices you care about (it's a bit of a crippled C++ then, but you still get objects and templates).

Upvotes: 1

kol
kol

Reputation: 28718

The Loki library may help you, it has a SmartPtr class. It uses std (std::swap, std::runtime_error), but it does not seem to be too hard to get rid of it.

Upvotes: 2

Related Questions