这可以通过静态键入来完成吗

Can this be done with static typing?

本文关键字:可以通过 静态      更新时间:2023-10-16

此方法尝试基于密钥(std::string)选择(std::vector<?>),其中?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++方法可以实现这一点?

这些都是模板这一事实与此无关。std::vector<std::vector<int> >std::vector<std::vector<float> >是两个完全不相关的类,并表现为这样。如果你真的需要这样,您就必须定义一个抽象基类和两个派生类,每个派生类包装相应的CCD_ 10。但我看不出你将如何使用它,或者甚至定义一个适当的抽象基类,因为类型包含在矢量中的矢量渗透到界面中。您的类型几乎每次通话中的使用也必须有所不同。

如果变量数量有限(即只有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这样的变量来识别变量类型仍然不好。