Search code examples
c++boostmake-shared

boost make_shared without template argument


I'm trying to pass a pointer to a stack variable to a function (I don't control) that only takes a boost::shared_ptr.

According to this answer, using boost::make_shared is the way to go. In order to test out this functionality I wrote this:

#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>

int main(int argc, char const *argv[])
{
    int i = 10;
    boost::shared_ptr<int> int_ptr = boost::make_shared(i); // doesn't work
    some_function(int_ptr); // this function takes only shared_ptr
    return 0;
}

But it throws the following error:

error: no matching function for call to ‘make_shared(int&)’
boost::shared_ptr<int> int_ptr = boost::make_shared(i);
                                                     ^

If I add the template argument like so it works but what is the reason for this?

boost::shared_ptr<int> int_ptr = boost::make_shared<int>(i);

Thank you!


Solution

  • Given the boost::make_shared<T> template:

    namespace boost {
        template<typename T, typename Arg1>
          shared_ptr<T> make_shared( Arg1 const & arg1 );
    }
    

    The template mechanism can deduce the type of parameter arg1. Because it "sees" the type of the argument i (which is int). However, it can't deduce the return type T. It does not know the type T of the boost::shared_ptr<T> you will assign to (i.e. it has no means to know the type of int_ptr.)

    The boost::shared_ptr<T> uses different types for argument (Arg1) and return (T) to allow you to build shared pointers from arguments different from the pointer type. For instance, double to int:

    double d = 10.0;
    std::shared_ptr<int> int_ptr = std::make_shared<int>(d);
    

    If you want to build shared pointers which the type is the same as the argument, you can write a wrapper:

    template<typename T>
    boost::shared_ptr<T> my_make_shared(T const & arg) {
        return boost::make_shared<T>(arg);
    }
    

    But bear in mind that while this works:

    int i = 10.0;
    std::shared_ptr<int> int_ptr = my_make_shared(i); // OK
    

    The implicit type conversion does not:

    double d = 10.0;
    std::shared_ptr<int> int_ptr = my_make_shared(d); // ERROR
    

    Hope it helps!