我有一个课程模板:
template<class idxT>
class SimpleGraph {
private:
// ...
std::set<std::pair<idxT,idxT>> edgeSet;
// ...
void addEdge(idxT a, idxT b);
// ...
}
edgeSet.emplace(a,b)
内使用addEdge()
的返回值,以下表示为r
。 r
的声明和分配需要分开,因为a
和b
的值由if-else语句决定。因此,我不能使用
auto r = edgeSet.emplace(a,b);
我尝试了以下策略,但都没有成功。第一个是
std::pair<decltype(edgeSet)::iterator,bool> r;
// some code
r = edgeSet.emplace(a,b);
第二个是
// inside class template
typedef std::set<std::pair<idxT,idxT>> EdgeSetType;
EdgeSetType edgeSet;
// inside definition of `addEdge()`
std::pair<EdgeSetType::iterator,bool> r;
// some code
r = edgeSet.emplace(a,b);
如何声明edgeSet.emplace(a,b)
的返回?
#include <set> // set
#include <utility> // pair
#include <iostream>
template<class idxT>
class SimpleGraph {
public:
void test(void);
private:
std::set<std::pair<idxT,idxT>> edgeSet;
void addEdge(idxT a, idxT b);
};
template<class idxT>
void SimpleGraph<idxT>::test(void) {
addEdge(1,2);
addEdge(1,2);
}
template<class idxT>
void SimpleGraph<idxT>::addEdge(idxT a, idxT b) {
std::pair<decltype(edgeSet)::iterator,bool> r;
if (a < b) {
r = edgeSet.emplace(a,b);
}
else {
r = edgeSet.emplace(a,b);
}
if (!r.second) {
std::cerr << "Error on (" << a << ',' << b <<"): "
<< "mutiple edges are not allowed for a simple graph.\n";
exit(1);
}
}
int main(void) {
SimpleGraph<int> graph;
graph.test();
}
clang抱怨说
test.cpp:24:13: error: template argument for template type parameter must be a type; did you forget 'typename'?
std::pair<decltype(edgeSet)::iterator,bool> r;
另请参阅here了解gcc生成的编译时错误。
答案 0 :(得分:1)
clang ++编译器实际上暗示了解决方案“你忘了'typename'吗?”
由于decltype(edgeSet)
依赖于类型(它间接依赖于模板参数idxT
),因此编译器在首次解析模板时不能只查找它,因此C ++会假设任何名称以下decltype(edgeSet)::
是变量或函数。因为它实际上是一种类型,所以你需要使用关键字typename
:
std::pair<typename decltype(edgeSet)::iterator,bool> r;
更多详细信息请参阅问题Where and why do I have to put the “template” and “typename” keywords?
的答案或者,请注意,任何有效的表达式都可以在decltype
中使用。 (这是一个未评估的上下文,这意味着如果你使用函数调用,隐式转换等,实际上不会为该表达式调用任何函数。)所以你也可以这样做:
decltype(edgeSet.emplace(a,b)) r;