考虑以下类别:
template<class a>
class c
{
public:
int x = 0;
// not really templated
friend constexpr auto operator +( int const left,
c const & a ) noexcept
{
return c{ left + x };
}
};
如何在不声明外部范围的情况下移动功能体?例如伪:template<class a>
friend constexpr auto c<a>::operator +( int const left,
c const & a ) noexcept
{
return c{ left + x };
}
最佳答案
OP的第一段:
class c
{
public:
int x = 0;
friend constexpr auto operator +( int const left,
c const & a ) noexcept
{
return c{ left + x };
}
};
它显示了一个免费函数(运算符),该函数在class c
中内联定义为friend
。尽管乍一看,它不是
class c
的成员函数。(如果它是一个成员函数,它将是一个三元运算符+,但是C++中不存在一个,也不能被重载。)
OP的第二个片段:
friend constexpr auto c::operator +( int const left,
c const & a ) noexcept
{
return c{ left + x };
}
错误有两个原因:friend
没有任何意义。 (friend
是什么?)c::
没有任何意义。函数的友谊不能在resp之外声明。类。
如果允许这样做,那么每个人都可以在访问类的
private
成员的任何地方声明函数的友好性。这会使private
成员毫无意义。(想象一下一个带电子锁和键盘的保险箱,密码写在门上。)
(原始图片由Binarysequence-自己的作品,CC BY-SA 4.0和Link)
尽管如此,
friend
函数(和运算符)当然可以非内联定义。以下示例显示了如何:
#include <iostream>
// forward declaration of class c
class c;
// forward declaration of operator +
constexpr auto operator+(int, c const&) noexcept;
// the class c
class c {
// make operator + a friend to grant access to private members
friend constexpr auto operator+(int, c const&) noexcept;
private:
int x;
public:
c() = default;
constexpr c(int x): x(x) { }
int get() const { return x; }
};
// the operator +
constexpr auto operator+(int lhs, c const &rhs) noexcept
{
return c(lhs + rhs.x);
}
// show it in action:
#define DEBUG(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__
int main()
{
DEBUG(c a(123));
DEBUG(std::cout << (234 + a).get() << '\n');
}
输出:c a(123);
std::cout << (234 + a).get() << '\n';
357
Live Demo on coliru应用于模板时,这是相似的(尽管语法有些棘手):
#include <iostream>
// forward declaration of class c
template <typename T>
class c;
// forward declaration of operator +
template <typename T>
constexpr auto operator+(int, c<T> const&) noexcept;
// the class c
template <typename T>
class c {
friend constexpr auto operator+<>(int, c<T> const&) noexcept;
private:
T x;
public:
c() = default;
constexpr c(T x): x(x) { }
int get() const { return x; }
};
// the operator +
template <typename T>
constexpr auto operator+(int lhs, c<T> const &rhs) noexcept
{
return c(lhs + rhs.x);
}
// show it in action:
#define DEBUG(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__
int main()
{
DEBUG(c<int> a(123));
DEBUG(std::cout << (234 + a).get() << '\n');
}
输出:c<int> a(123);
std::cout << (234 + a).get() << '\n';
357
Live Demo on coliru有关内联好友功能的更多信息:
关于c++ - 移动ADL friend 声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62945043/