Search code examples
c++11shared-ptrc2664

c++ std::shared_ptr Error C2664


I am using a std::shared_ptr to point to a Node

template<typename T>
class A
{
    class Node
    {
       T data;
       std::shared_ptr<Node> link;
       Node(T data, std::shared_ptr<Node> link);
    };
    void push(T data);
    std::shared_ptr<Node> top;
};

template<typename T>
A<T>::Node::Node(T data, std::shared_ptr<typename A<T>::Node> link) : 
data(data), link(link)
{
}

template<typename T>
void A<T>::push(T item)
{
    if (top == nullptr)
    {
       top = std::make_shared<typename A<T>::Node>(new typename 
                                                    A<T>::Node(item, nullptr));
    }
    else
    {
       top = std::make_shared<typename A<T>::Node>(new typename A<T>::Node(item, top));
    }
}

The resulting declarations and definitions results in the compiler error

Severity Code Description Project File Line Suppression State Error C2664 'Stack::Node::Node(const Stack::Node &)': cannot convert argument 1 from 'Stack::Node *' to 'const Stack::Node &' memory 901

What do I need to change to conform to <memory>?


Solution

  • A constructor of std::shared_ptr<T> accepts a pointer to T which you have created with new.

    The function std::make_shared<T>(args...) does the new for you instead. The arguments you pass to make_shared will be passed on to the constructor of T. So you should almost never pass it a pointer created by new (unless you really want to new a T, and then pass that pointer as an argument to create another T!).

    So for example, instead of:

    std::make_shared<typename A<T>::Node>(
       new typename A<T>::Node(item, top))
    

    do just:

    std::make_shared<typename A<T>::Node>(item, top)
    

    (By the way, you don't actually need most of those typename A<T>:: qualifiers. Just plain Node is in scope whenever you're in the scope of A<T> or A<T>::Node, both in the class definitions and member definitions of that class after the member name. A<T>::Node without the typename would also work in those contexts because of the "member of the current instantiation" rule.)