c++ - 移动ADL friend 声明

标签 c++

考虑以下类别:

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成员毫无意义。
    (想象一下一个带电子锁和键盘的保险箱,密码写在门上。)
    A somehow useless safe
    (原始图片由Binarysequence-自己的作品,CC BY-SA 4.0Link)
    尽管如此,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

    有关内联好友功能的更多信息:
  • SO: friend AND inline method, what's the point ?
  • SO: c++ implementing friend/inline functions(类似问题)
  • SO: Nonmember friend function is always inline(类似问题)
  • 关于c++ - 移动ADL friend 声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62945043/

    相关文章:

    c++ - 我的堆排序算法时间复杂度分析是否正确?

    c++ - 尝试使用匿名 union 引用已删除的函数错误

    c++ - 为 Visual Studio 2013 构建 cgicc-3.2.16

    C++ 数组显示字母和数字?

    c++ - 这是在传递 int num 时创建搜索函数的正确方法吗?使用链表库

    c++ - 使用桥接模式 C++ 实现复制构造函数

    c++ - 确保指向父类(super class)的指针指向C++中某个子类的对象

    c++ - 模板 :Function template specializations:Template argument deduction: -->can any one tell some more examples for this statement?

    c++ - 将多个数组转换为元组

    C++ 默认参数值使用另一个参数的值