Template Class wrong copy constructor called

c++, templates

Solution

Your problem is essentially caused by this member:

std::auto_ptr<AlgorithmInterface<Weight> > _algorithm;

`std::auto_ptr`'s copy constructor doesn't really copy, it transfers ownership. Because of this it takes a non-const reference to its argument, not a const reference.

This means that when the compiler comes to generate the copy constructor for an `MPINode` specialization it cannot generate a copy constructor that takes a const reference to another `MPINode`, it can only generate one that takes a non const reference.

In this initialization, the temporary `MPINode<WeightValue>` cannot bind to the non-const reference parameter that the generated copy constructor requires.

MPINode<WeightValue> node = MPINode<WeightValue>(alg, nodeType, 
      tempNodeId, _nodeDistribution, _localNodes);

How to fix this depends on your design. It might be that supplying a user-defined copy constructor that takes const reference and properly clones the `_algorithm` member is the correct approach.

Problem

Solution To avoid the problem with the std::auto_ptr one can switch to boost::shard_ptr or C++11 std::shared_ptr. I get an error that the wrong copy constructor is called in my template class: ``` MPINetworkCode.hpp: error: no matching function for call to MPILib::MPINode<double>::MPINode(MPILib::MPINode<double>) MPINode.hpp: note: candidate is: MPILib::MPINode<double>::MPINode(MPILib::MPINode<double>&) ``` Here are the code lines which result in this error. ``` int MPINetwork<WeightValue>::AddNode(const AlgorithmInterface<WeightValue>& alg, NodeType nodeType) { MPINode<WeightValue> node = MPINode<WeightValue>(alg, nodeType, tempNodeId, _nodeDistribution, _localNodes); _localNodes.insert(std::make_pair(tempNodeId, node)); } ``` What is wrong with this code, and why is the wrong copy constructor is called? In a previous version of this class without templates this worked fine. Here the header of the related classes. The template implementation are in a header file. Here the MPINetwork: ``` template <class WeightValue> class MPINetwork: private boost::noncopyable { public: explicit MPINetwork(); ~MPINetwork(); /** * Adds a new node to the network * @param alg The Algorithm of the actual node * @param nodeType The Type of the Node * @return returns the NodeId of the generated node */ int AddNode(const AlgorithmInterface<WeightValue>& alg, NodeType nodeType); //lot of code }; ``` And the second MPINode, where the default copy constructor should be called: ``` template <class Weight> class MPINode { public: /** * Constructor * @param algorithm Algorithm the algorithm the node should contain * @param nodeType NodeType the type of the node * @param nodeId NodeId the id of the node * @param nodeDistribution The Node Distribution. * @param localNode The local nodes of this processor */ explicit MPINode(const AlgorithmInterface<Weight>& algorithm, NodeType nodeType, NodeId nodeId, const boost::shared_ptr<utilities::NodeDistributionInterface>& nodeDistribution, const std::map<NodeId, MPINode<Weight> >& localNode); virtual ~MPINode(); Time Evolve(Time time); void ConfigureSimulationRun(const SimulationRunParameter& simParam); void addPrecursor(NodeId nodeId, const Weight& weight); void addSuccessor(NodeId nodeId); NodeState getState() const; void setState(NodeState state); void receiveData(); void sendOwnState(); private: void waitAll(); std::vector<NodeId> _precursors; std::vector<Weight> _weights; std::vector<NodeId> _successors; std::auto_ptr<AlgorithmInterface<Weight> > _algorithm; NodeType _nodeType; NodeId _nodeId; const std::map<NodeId, MPINode>& _refLocalNodes; boost::shared_ptr<utilities::NodeDistributionInterface> _nodeDistribution; NodeState _state; std::vector<NodeState> _precursorStates; std::vector<boost::mpi::request> _mpiStatus; }; template<class Weight> MPINode<Weight>::MPINode(const AlgorithmInterface<Weight>& algorithm, NodeType nodeType, NodeId nodeId, const boost::shared_ptr<utilities::NodeDistributionInterface>& nodeDistribution, const std::map<NodeId, MPINode>& localNode) : _algorithm(algorithm.Clone()), _nodeType(nodeType), _nodeId(nodeId), _nodeDistribution( nodeDistribution), _refLocalNodes(localNode) { } ```

Original source