【问题标题】:Complicated operator overloading and templates复杂的运算符重载和模板
【发布时间】:2013-12-05 15:04:10
【问题描述】:

这是 C++ 中一个非常疯狂的定点算术实现。拜托,请不要告诉我这一切有多糟糕和毫无意义。

如您所见,有一个基本类型T和一个二进制数字的小数部分N。需要将FixedNum<int, A> + FixedNum<int, B> 评估为FixedNum<int, MAX(A, B)>. 这是我尝试实现它的方法。但是,GCC 说最后几行中对x 的分配是错误的,因为x 是受保护的。怎么了?

#define MAX(a,b) (((a)>(b))?(a):(b))

template <typename T, int N>
class FixedNum
{
    public:
        template <int N2>
        friend FixedNum& operator+(const FixedNum& f, const FixedNum& g);
        template <int N2>
        friend FixedNum& operator+=(const FixedNum& f, const FixedNum& g);
        FixedNum(T x): x (x) {}

        T num() const { return x; }
        int point() const { return N; }

    protected:
        T x;
};

template <typename T, int N, int N2>
FixedNum<T, MAX(N, N2)>& operator+(const FixedNum<T, N>& f, const FixedNum<T, N2>& g)
{
    return FixedNum<T, N>(f) += g;
}

template <typename T, int N, int N2>
FixedNum<T, MAX(N, N2)>& operator+=(const FixedNum<T, N>& f, const FixedNum<T, N2>& g)
{
#if N2 <= N
    f.x += g.x << (N-N2);
#else
    f.x <<= (N2-N);
    f.x += g.x;
#endif
}

【问题讨论】:

  • x 确实受到保护,显然您正试图将 operator+= 声明为朋友。但我认为您的朋友声明与您实现的运算符不匹配。
  • 我不相信模板的不同专业可以相互访问protected 变量,除非专业是朋友。见stackoverflow.com/questions/11001480/…

标签: c++ templates operator-overloading friend


【解决方案1】:

您必须使用bool 选择器模板并将其专门用于N2 &lt;= N,而不是使用#if #else #endif。预处理器根本看不到模板实例化。

【讨论】:

    【解决方案2】:

    模板类类型的每个实例化都是不同的类。
    请记住,这些类实际上具有不同的名称,并且与继承无关。

    FixedNum&lt;int,5&gt; 是一个唯一名称,将不同于类类型FixedNum&lt;int,6&gt;
    因此他们无法访问彼此的受保护成员。

    您必须将所有“相似”的模板类作为好友进行 decalare,如下所示:

    template<typename T, int N> friend class FixedNum;
    

    除此之外,使用预处理器 #if 不会像你想要的那样工作。
    预处理器,就像它的名字一样,在编译器开始处理所有代码之前进行处理。所以它只评估 MACRO 值和预处理器定义。

    【讨论】:

      【解决方案3】:

      也许是这样的:

      #include <iostream>
      
      template <typename T, int N>
      class FixedNum
      {
          public:
          FixedNum(T x): x (x) {}
      
          T num() const { return x; }
          int point() const { return N; }
      
          // A += with a FixedNum with a different N is pointless.
          FixedNum& operator+=(const FixedNum& g) {
              x += g.x;
              return *this;
          }
      
          protected:
          T x;
      };
      
      
      // A helper class to provide the result type and operation.
      template <typename T, int N1, int N2>
      struct FixedNumAdd
      {
          typedef FixedNum<T, (N1 < N2) ? N2 : N1> result_type;
          static result_type apply(const FixedNum<T, N1>& f, const FixedNum<T, N2>& g) {
              if(N1 < N2) {
                  T x = f.num();
                  for(int i = N1; i < N2; ++i) x *= 10;
                  return result_type(x) += g.num();
              }
              else {
                  T x = g.num();
                  for(int i = N2; i < N1; ++i) x *= 10;
                  return result_type(x) += f.num();
              }
          }
      };
      
      template <typename T, int N1, int N2>
      inline typename::FixedNumAdd<T, N1, N2>::result_type
      operator + (const FixedNum<T, N1>& f, const FixedNum<T, N2>& g)
      {
          return FixedNumAdd<T, N1, N2>::apply(f, g);
      }
      
      int main() {
          FixedNumAdd<int, 1, 2>::result_type result
              = FixedNum<int, 1>(11)
              + FixedNum<int, 2>(13);
          std::cout <<  double(result.num()) / 100 << std::endl;
          return 0;
      }
      

      (使用 C++11 和 auto 会更好)

      【讨论】:

        猜你喜欢
        • 2016-02-03
        • 2021-09-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-15
        • 1970-01-01
        • 1970-01-01
        • 2022-10-01
        相关资源
        最近更新 更多