【问题标题】:Can this be done with static typing?这可以通过静态类型来完成吗?
【发布时间】:2013-02-07 18:59:23
【问题描述】:

此方法尝试根据键 (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&lt;?&gt;) 未初始化。但是为了初始化它,我必须在编译时知道它的类型。

也许我正在尝试使用静态类型无法完成。有没有 C++ 方法来完成这个?

【问题讨论】:

  • 运行时不能选择类型,不行。 auto 仍然只在编译时有效。但是,您可以编写两个不同的函数并根据字符串调用正确的函数。
  • @BoPersson 但是编译时不知道可能的字符串(键)。你的想法仍然有效吗?
  • 您似乎在intfloat 之间进行选择。只需为每个变体编写一个函数,然后调用需要的函数。

标签: c++ c++11 static-typing dynamic-typing


【解决方案1】:

这些是模板的事实与它无关。 std::vector&lt;std::vector&lt;int&gt; &gt;std::vector&lt;std::vector&lt;float&gt; &gt; 是两个完全不相关的 类,并表现得如此。如果你真的需要类似的东西 这个,你必须定义一个抽象基类和两个 派生类,每个派生类都包装了相应的 std::vector。但我不知道你将如何使用它,或者 甚至定义一个适当的抽象基类,因为类型 包含在向量中的元素渗透到界面中。你的类型 几乎在每次通话中的使用也必须有所不同。

【讨论】:

    【解决方案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之类的变量来识别变量类型还是不好的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-26
      • 1970-01-01
      相关资源
      最近更新 更多