此方法尝试根据键(std::vector<?>
)选择(std::string
),其中?
为int
或float
:
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 ++方法来实现这一目标?
答案 0 :(得分:2)
这些是模板的事实与它无关。
std::vector<std::vector<int> >
和
std::vector<std::vector<float> >
是两个完全无关的
类,并表现如此。如果你真的需要类似的东西
这个,你必须定义一个抽象基类和两个
派生类,每个包装相应的
std::vector
。但我不知道你将如何使用它,或者
甚至定义一个合适的抽象基类,因为类型
包含在载体中的是渗透界面。你的类型
在几乎每次通话中使用也必须是不同的。
答案 1 :(得分: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的变量来识别变量类型仍然不太好。