boost make_shared takes in a const reference. Any way to get around this?
Asked Answered
B

6

38

I am using boost shared pointers in my program, and I have a class that takes as a parameters a reference to another object. The problem I am running into is the make_shared function requires all parameters to be a const reference, and I get compile errors if my class's constructor doesn't allow const reference parameters to be passed in.

Does anyone know the reason behind this? Also, is there anything I can do to get around this?

code example of what is giving me problems:

class Object
{
  public:
    Object(int& i)
    {
      i = 2;
    }
};


int main(int argc, char *argv[])
{
  int i = 0;
  boost::shared_ptr<Object> obj = boost::make_shared<Object>(i);
  return 1;
}

This results in a compiler error that states the following

:make_shared.hpp:185: error: no matching function for call to `Object::Object(const int&)' note: candidates are: Object::Object(const Object&) note: Object::Object(int&)

If the parameter to Objects constructor is a const int, this works. I am curious as to why make_shared behaves this way.

Blackcap answered 3/9, 2009 at 14:51 Comment(1)
Can you show us some code to demonstrate how you want to use make_shared() ?Suzannsuzanna
L
43

http://www.boost.org/doc/libs/1_39_0/libs/smart_ptr/make_shared.html says: "If you need to pass a non-const reference to a constructor of T, you may do so by wrapping the parameter in a call to boost::ref." Other text on that page seems to support Rüdiger Hanke's answer.

Lutz answered 3/9, 2009 at 15:47 Comment(1)
awesome, thanks I really didn't want to use my workaround below.Blackcap
U
8

Can't speak for the authors of he function, but ... you've got to make a choice. If the function would use a non-const reference, then you couldn't pass const objects to constructors that take const references.

In my experience, constructors taking const references are far more common than constructors taking mutable references.

Constructors can have n parameters, so you can't just provide a single overload, but have to take into account any combination of const/non-const which results in an exponential explosion of overloads you'd need if you'd want to provide overloads for all of them. C++0x and perfect forwarding should provide a solution for this issue I think.

Upandcoming answered 3/9, 2009 at 15:44 Comment(1)
Perfect explanation. Thanks.Blackcap
A
5

Until rvalue references (see the section titled "the forwarding problem") arrive in C++0x, perfect forwarding is next to impossible. make_shared just does the best it can with what it's given.

Arrow answered 3/9, 2009 at 15:46 Comment(3)
+1 Somebody actually posted an explanation why this is and not just use boost::ref(..) :)Jazminejazz
The link is broken.Ctenidium
@Ctenidium thanks, fixed, although I think every compiler has added rvalue references in the last decade. :)Arrow
B
1

You need to define a copy constructor.

class Object
{
  public:
    Object(const Object& original)
    {
        // Copy original to new object
        // The reason for the const is this should not change the original 
    };

    Object(int& i)
    {
      i = 2;
    }
};
Bereniceberenson answered 3/9, 2009 at 15:44 Comment(0)
B
0

While I still have no idea why boost make_shared imposes this limitation on me, I have found a way around it. If I pass in a const reference to a pointer of the parameter, I can then change the pointer. Here is the code snippet:

class Object
{
  public:
    Object(int* const& i)
    {
      *i = 2;
    }
};


int main(int argc, char *argv[])
{
  int i = 0;
  boost::shared_ptr<Object> obj = boost::make_shared<Object>(&i);
  cout << i << "\n";
  return 1;
}

This one works like a charm. Anyone have any idea why I need to jump through these hoops though? Seems strange for make_shared to impose this limitation on me, even though I agree it is probably a bad idea most of the time.

Blackcap answered 3/9, 2009 at 15:38 Comment(0)
G
0

You might be able to fix it by making the Object constructor explicit.

Goingover answered 3/9, 2009 at 15:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.