【发布时间】:2020-06-02 07:26:09
【问题描述】:
直到 C++ 的 C++20 标准,当我们想要定义一个使用模板类的一些私有成员的类外运算符时,我们会使用类似于这样的构造:
template <typename T>
class Foo;
template <typename T>
constexpr bool operator==(T lhs, const Foo<T>& rhs);
template <typename T>
class Foo {
public:
constexpr Foo(T k) : mK(k) {}
constexpr friend bool operator==<T>(T lhs, const Foo& rhs);
private:
T mK;
};
template <typename T>
constexpr bool operator==(T lhs, const Foo<T>& rhs) {
return lhs == rhs.mK;
}
int main() {
return 1 == Foo<int>(1) ? 0 : 1;
}
然而,从 C++20 开始,我们可以省略类外声明,因此也可以省略前向声明,所以我们可以只做:
template <typename T>
class Foo {
public:
constexpr Foo(T k) : mK(k) {}
constexpr friend bool operator==<T>(T lhs, const Foo& rhs);
private:
T mK;
};
template <typename T>
constexpr bool operator==(T lhs, const Foo<T>& rhs) {
return lhs == rhs.mK;
}
现在,我的问题是,C++20 的哪一部分允许我们这样做?为什么在早期的 C++ 标准中不可能做到这一点?
正如 cmets 中所指出的,clang 不接受演示中提供的此代码,这表明这实际上可能是 gcc 中的错误。
我在 gcc 的 bugzilla 上提交了 bug report
【问题讨论】:
-
我个人更喜欢在类定义中,避免模板函数(和推导“问题”(不匹配
"c string" == Foo<std::string>("foo")))。 -
@Jarod42 我完全同意,我也更喜欢课堂定义。我只是惊讶地发现 C++20 允许我们在定义它的类中时不重复函数签名三次,这在实现位于隐藏 .inl 文件中的公共 API 中可能很有用。
-
我没有注意到这是不可能的。为什么我使用它至今没有问题?
-
嗯,在 temp.friend 中,没有太大变化,尤其是 1.3 应该对此行为负责。由于 clang 不 接受你的代码,我倾向于 gcc 有一个错误。
-
@ALX23z 如果类没有模板化,它可以在没有类外声明的情况下工作。