我一直在编写几个包含嵌套迭代器类的类模板,需要进行相等比较。我认为这是相当典型的,比较是使用非成员(和非朋友)operator==
函数执行的。这样做,我的编译器(我使用带有标志-O3 -g -Wall
的Mingw32 GCC 4.4)无法找到该函数,并且我已经用尽了可能的原因。
在下面相当大的代码块中有三个类:一个Base类,一个包含Base对象的Composed类,以及一个与Composed类相同的嵌套类,除了它嵌套在一个Outer类中。为每个提供非成员operator==
功能。这些类是模板化和未模板化的形式(在各自的命名空间中),后者等同于前者专用于无符号整数。
在main
中,比较每个类的两个相同对象。对于未计算的情况,没有问题,但对于模板化情况,编译器无法找到operator==
。发生了什么事?
#include <iostream>
namespace templated {
template<typename T>
class Base {
T t_;
public:
explicit Base(const T& t) : t_(t) {}
bool
equal(const Base& x) const {
return x.t_==t_;
}
};
template<typename T>
bool
operator==(const Base<T> &x, const Base<T> &y) {
return x.equal(y);
}
template<typename T>
class Composed {
typedef Base<T> Base_;
Base_ base_;
public:
explicit Composed(const T& t) : base_(t) {}
bool equal(const Composed& x) const {return x.base_==base_;}
};
template<typename T>
bool
operator==(const Composed<T> &x, const Composed<T> &y) {
return x.equal(y);
}
template<typename T>
class Outer {
public:
class Nested {
typedef Base<T> Base_;
Base_ base_;
public:
explicit Nested(const T& t) : base_(t) {}
bool equal(const Nested& x) const {return x.base_==base_;}
};
};
template<typename T>
bool
operator==(const typename Outer<T>::Nested &x,
const typename Outer<T>::Nested &y) {
return x.equal(y);
}
} // namespace templated
namespace untemplated {
class Base {
unsigned int t_;
public:
explicit Base(const unsigned int& t) : t_(t) {}
bool
equal(const Base& x) const {
return x.t_==t_;
}
};
bool
operator==(const Base &x, const Base &y) {
return x.equal(y);
}
class Composed {
typedef Base Base_;
Base_ base_;
public:
explicit Composed(const unsigned int& t) : base_(t) {}
bool equal(const Composed& x) const {return x.base_==base_;}
};
bool
operator==(const Composed &x, const Composed &y) {
return x.equal(y);
}
class Outer {
public:
class Nested {
typedef Base Base_;
Base_ base_;
public:
explicit Nested(const unsigned int& t) : base_(t) {}
bool equal(const Nested& x) const {return x.base_==base_;}
};
};
bool
operator==(const Outer::Nested &x,
const Outer::Nested &y) {
return x.equal(y);
}
} // namespace untemplated
int main() {
using std::cout;
unsigned int testVal=3;
{ // No templates first
typedef untemplated::Base Base_t;
Base_t a(testVal);
Base_t b(testVal);
cout << "a=b=" << testVal << "\n";
cout << "a==b ? " << (a==b ? "TRUE" : "FALSE") << "\n";
typedef untemplated::Composed Composed_t;
Composed_t c(testVal);
Composed_t d(testVal);
cout << "c=d=" << testVal << "\n";
cout << "c==d ? " << (c==d ? "TRUE" : "FALSE") << "\n";
typedef untemplated::Outer::Nested Nested_t;
Nested_t e(testVal);
Nested_t f(testVal);
cout << "e=f=" << testVal << "\n";
cout << "e==f ? " << (e==f ? "TRUE" : "FALSE") << "\n";
}
{ // Now with templates
typedef templated::Base<unsigned int> Base_t;
Base_t a(testVal);
Base_t b(testVal);
cout << "a=b=" << testVal << "\n";
cout << "a==b ? " << (a==b ? "TRUE" : "FALSE") << "\n";
typedef templated::Composed<unsigned int> Composed_t;
Composed_t c(testVal);
Composed_t d(testVal);
cout << "c=d=" << testVal << "\n";
cout << "d==c ? " << (c==d ? "TRUE" : "FALSE") << "\n";
typedef templated::Outer<unsigned int>::Nested Nested_t;
Nested_t e(testVal);
Nested_t f(testVal);
cout << "e=f=" << testVal << "\n";
cout << "e==f ? " << (e==f ? "TRUE" : "FALSE") << "\n";
// Above line causes compiler error:
// error: no match for 'operator==' in 'e == f'
}
cout << std::endl;
return 0;
}
答案 0 :(得分:5)
对于带有模板的嵌套类,这个问题很常见。
template <class T>
struct Outer { struct Inner {}; };
template <class T>
void increment(typename Outer<T>::Inner&) {}
找不到increment
功能。我认为查找起来太难以让编译器解决。
你可以缓解这个问题,
namespace detail
{
template <class T> struct InnerImpl {};
template <class T> void increment(InnerImpl& ) {}
}
template <class T>
struct Outer
{
typedef detail::InnerImpl<T> Inner;
};
int main(int argc, char* argv[])
{
Outer<int>::Inner inner;
increment(inner); // works
}
好笑,不是吗?
根据经验,免费方法的参数(不是结果类型)中的typename
是一个红色鲱鱼,似乎阻止了自动参数推断。
答案 1 :(得分:0)
如果您没有重载operator&amp;,那么只需比较内存地址。没有必要这样做。
答案 2 :(得分:0)
在接受答案之后,我想到了如何以最小的努力来最好地修复我的代码。通过更清楚地了解问题,我从C++ FAQ获得了新的灵感,并将非成员operator==
合并为类定义作为友元函数。这并不像听起来那么多,因为提供equal()
成员函数的原因是为了避免朋友的需要,但对于模板,友元函数的好处是允许函数定义在班级内部举行,从而避免查询问题。
template<typename T>
class Outer {
public:
class Nested {
typedef Base<T> Base_;
Base_ base_;
friend bool operator==(Nested const &x, Nested const &y) {
return x.base_==y.base_;
}
public:
explicit Nested(const T& t) : base_(t) {}
};
};