提问人:TheMemeMachine 提问时间:9/14/2023 更新时间:9/14/2023 访问量:56
在另一个模板类 [duplicate] 中的类中定义友元运算符==时出错
Error when defining friend operator== in a class within another template class [duplicate]
问:
我有一个模板类和另一个类。我必须为该内部类定义 operator==,但定义和定义是分开的。下面是一个最小的可重现示例:
#include <iostream>
namespace myNamespace {
template <typename T>
class MyClass {
public:
class MyInnerClass {
public:
MyInnerClass() : v{0} {};
// declaration
template <typename U>
friend bool operator==(const typename MyClass<U>::MyInnerClass& lhs, const typename MyClass<U>::MyInnerClass& rhs);
private:
int v;
};
private:
// ...
};
}
namespace myNamespace {
// definition
template <typename U>
bool operator==(const typename MyClass<U>::MyInnerClass& lhs, const typename MyClass<U>::MyInnerClass& rhs) {
return lhs.v == rhs.v;
}
}
int main() {
using namespace myNamespace;
MyClass<int>::MyInnerClass inner1;
MyClass<int>::MyInnerClass inner2;
// fails here
std::cout << (inner1 == inner2) << std::endl;
return 0;
}
我得到的错误是:
tmp.cpp:39:26: error: no match for ‘operator==’ (operand types are ‘myNamespace::MyClass<int>::MyInnerClass’ and ‘myNamespace::MyClass<int>::MyInnerClass’)
39 | std::cout << (inner1 == inner2) << std::endl;
| ~~~~~~ ^~ ~~~~~~
| | |
| | MyInnerClass<[...]>
| MyInnerClass<[...]>
tmp.cpp:27:10: note: candidate: ‘template<class U> bool myNamespace::operator==(const typename myNamespace::MyClass<U>::MyInnerClass&, const typename myNamespace::MyClass<U>::MyInnerClass&)’
27 | bool operator==(const typename MyClass<U>::MyInnerClass& lhs, const typename MyClass<U>::MyInnerClass& rhs) {
| ^~~~~~~~
tmp.cpp:27:10: note: template argument deduction/substitution failed:
tmp.cpp:39:29: note: couldn’t deduce template parameter ‘U’
39 | std::cout << (inner1 == inner2) << std::endl;
| ^~~~~~
我如何使模板运算符==专业化,这样就不会失败
答:
0赞
Eugene
9/14/2023
#1
不要为 - use(外部类模板参数)引入新的模板参数。此外,您必须将定义与声明结合起来(因为以这种方式声明的只有通过 ADL 才能看到):friend
T
friend
#include <iostream>
namespace myNamespace {
template <typename T>
class MyClass {
public:
class MyInnerClass {
public:
MyInnerClass() : v{ 0 } {};
friend bool operator==(const typename MyClass<T>::MyInnerClass& lhs, const typename MyClass<T>::MyInnerClass& rhs)
{
return lhs.v == rhs.v;
}
private:
int v;
};
private:
// ...
};
}
评论
0赞
TheMemeMachine
9/14/2023
我在这里很困惑。为什么在这种情况下我不能将声明和定义分开,但是如果我在类中没有类,我可以这样做?下面是一个编译良好的示例:godbolt.org/z/8h77eGMY4
1赞
Jan Schultke
9/14/2023
#2
窗体的运算符重载
template <typename U>
bool operator==(const typename MyClass<U>::MyInnerClass& lhs,
const typename MyClass<U>::MyInnerClass& rhs);
...无论在哪里定义它,实际上都是无用的,因为这是一个非推导的上下文。从这样的函数参数中推导出是不可能的,所以调用它的唯一方法是通过MyClass<U>::MyInnerClass
U
myNamespace::operator==<MyType>(a, b);
相反,您可以将运算符重载定义为声明当前所在的隐藏友元:friend
// note: MyClass<T>:: can be omitted here
friend bool operator==(const MyInnerClass& lhs, const MyInnerClass& rhs) {
return lhs.v == rhs.v;
}
通常,此解决方案是可取的,因为它使运算符重载为非模板。
请参阅类似的问题:模板化类友元运算符成员函数
评论