3

解決

std::auto_ptr の問題を回避するには、boost::shard_ptr または C++11 std::shared_ptr に切り替えることができます。

テンプレート クラスで間違ったコピー コンストラクターが呼び出されたというエラーが表示されます。

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>&)

このエラーが発生するコード行は次のとおりです。

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));
}

このコードの何が問題なのですか? また、間違ったコピー コンストラクターが呼び出されるのはなぜですか? テンプレートのないこのクラスの以前のバージョンでは、これはうまくいきました。

ここに関連するクラスのヘッダーがあります。テンプレートの実装はヘッダー ファイルにあります。

ここで 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

};

そして、デフォルトのコピー コンストラクターを呼び出す必要がある 2 番目の MPINode:

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) {

}
4

3 に答える 3

5

あなたの問題は本質的にこのメンバーによって引き起こされます:

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

std::auto_ptrのコピー コンストラクターは実際にはコピーしません。所有権を譲渡します。このため、const 参照ではなく、その引数への非 const 参照を取ります。

これは、コンパイラがMPINode特殊化のためにコピー コンストラクターを生成するときに、別の への const 参照を取るコピー コンストラクターを生成できずMPINode、非 const 参照を取るコピー コンストラクターしか生成できないことを意味します。

この初期化では、一時MPINode<WeightValue>は、生成されたコピー コンストラクターが必要とする非 const 参照パラメーターにバインドできません。

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

これを修正する方法は、設計によって異なります。const 参照を取り、_algorithmメンバーを適切に複製するユーザー定義のコピーコンストラクターを提供することが正しいアプローチである可能性があります。

于 2012-06-05T08:46:34.720 に答える
2

コンパイラは、 type の引数を受け入れるコピー コンストラクターを生成しているようですMPILib::MPINode<double>&。type を取る独自のコピー コンストラクターを定義してみてくださいconst MPILib::MPINode<double>&。変数nodeinの初期化AddNodeはコピー コンストラクターを呼び出しており、コンパイラーは、変更可能な参照を期待する関数に一時変数を渡すことを許可しません。

于 2012-06-05T08:46:50.903 に答える
1

データメンバーとして(const参照を取るstd::auto_ptr<AlgorithmInterface<Weight> >「通常の」コピーコンストラクターはありませんが、残念ながら参照を取るひねくれたものがあります)があるため、コンパイラーはconstを取るデフォルトのコピーコンストラクターを生成できませんでした-参照。その場合、可能であれば、コンパイラは非 const 参照を取るものを生成します。あなたのコードはこれを呼び出そうとしますが、失敗します。

あなたはそれについて何をすべきですか

生成された「コピー」コンストラクターは実際にその引数からデータメンバーを盗むため、NOWを無効にします。次に、必要に応じて動作する独自のコピー コンストラクターを実装します。

于 2012-06-05T08:47:12.013 に答える