0

std::vector<?>このメソッドは、キー ( ) に基づいて( ) を選択しようとしますstd::string。ここで、?は または のいずれintfloatです。

template<typename L>
inline void EnsembleClustering::Graph::forNodesWithAttribute(std::string attrKey, L handle) {
    // get nodemap for attrKey

    auto nodeMap; // ?

    auto findIdPair = this->attrKey2IdPair.find(attrKey);
    if (findIdPair != this->attrKey2IdPair.end()) {
        std::pair<index, index> idPair = findIdPair->second;
        index typeId = idPair.first;
        index mapId = idPair.second;

        // nodemaps are in a vector, one for each node attribute type int, float, NodeAttribute
        switch (typeId) {
        case 0:
            nodeMap = this->nodeMapsInt[mapId];
            break;
        case 1:
            nodeMap = this->nodeMapsFloat[mapId];
            break;
        }

        // iterate over nodes and call handler with attribute
        this->forNodes([&](node u) {
            auto attr = nodeMap[u];
            handle(u, attr);
        });
    } else {
        throw std::runtime_error("node attribute not found");
    }

}

クラスの関連メンバーは次のとおりです。

std::map<std::string, std::pair<index, index>> attrKey2IdPair;  // attribute key -> (attribute type index, attribute map index)

// storage
std::vector<std::vector<int> > nodeMapsInt;         // has type id 0
std::vector<std::vector<float> > nodeMapsFloat;     // has type id 1

auto nodeMap(= std::vector<?>) が初期化されていないため、これはコンパイルされません。しかし、それを初期化するには、コンパイル時にその型を知る必要があります。

私が試みていることは、静的型付けでは実行できないかもしれません。これを達成するC++の方法はありますか?

4

2 に答える 2

2

これらがテンプレートであるという事実は、それとは何の関係もありません。 std::vector<std::vector<int> >std::vector<std::vector<float> >はまったく無関係な 2 つのクラスであり、そのように動作します。このようなものが本当に必要な場合は、抽象基本クラスと 2 つの派生クラスを定義する必要があります。それぞれが対応する をラップし std::vectorます。しかし、ベクトルに含まれる型がインターフェイスに浸透するため、それを使用する方法や、適切な抽象基本クラスを定義する方法さえわかりません。ほぼすべての呼び出しで使用する型も異なる必要があります。

于 2013-02-07T19:12:05.930 に答える
2

バリアントの数が限られている場合 (つまり、float のベクトルと int のベクトルのみ)、boost::variantそれを格納するために使用できます。

バリアントのタイプを定義し、訪問者の構造を定義します。

#include "boost/variant.hpp"

//Define type
typedef boost::variant<std::vector<int>, std::vector<float>> VectorType;

struct VectorTypeVisitor : public boost::static_visitor<void>
    {
        node& m_u;

        VectorTypeVisitor(node& u) : m_u(u) { } //Pass node to visitor in constructor

        void operator()(const std::vector<int>& nodeMap) const
        {
            auto attr = nodeMap[m_u];
            handle(m_u, attr);
        }

        void operator()(const std::vector<float>& nodeMap) const
        {
            auto attr = nodeMap[m_u];
            handle(m_u, attr); //What to do if visitor applied to float
        }
    }

コードは次のようになります。

template<typename L>
inline void EnsembleClustering::Graph::forNodesWithAttribute(std::string attrKey, L handle) {
    // get nodemap for attrKey

    VectorType nodeMap;

    auto findIdPair = this->attrKey2IdPair.find(attrKey);
    if (findIdPair != this->attrKey2IdPair.end()) {
        std::pair<index, index> idPair = findIdPair->second;
        index typeId = idPair.first;
        index mapId = idPair.second;

        // nodemaps are in a vector, one for each node attribute type int, float, NodeAttribute
        switch (typeId) {
        case 0:
            nodeMap = this->nodeMapsInt[mapId];
            break;
        case 1:
            nodeMap = this->nodeMapsFloat[mapId];
            break;
        }

        // iterate over nodes and call handler with attribute
        this->forNodes([&](node u) {
            boost::apply_visitor(VectorTypeVisitor(u), nodeMap);
        });
    } else {
        throw std::runtime_error("node attribute not found");
    }
}

しかし、変数の型を識別するために typeId のような変数を渡すのはまだ良くありません。

于 2013-02-07T19:43:45.843 に答える