这是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
}
答案 0 :(得分:5)
您必须使用bool
选择器模板并将其专门用于N2 <= N
,而不是使用#if
#else
#endif
。预处理器根本不会看到模板实例化。
答案 1 :(得分:3)
模板类类型的每个实例化都是不同的类 请记住,这些类实际上具有不同的名称,并且与继承无关。
FixedNum<int,5>
是一个唯一的名称,与类型FixedNum<int,6>
不同
因此,他们无法访问彼此受保护的成员。
你必须将所有“类似”模板化的课程视为朋友,如下所示:
template<typename T, int N> friend class FixedNum;
除此之外,使用预处理器 #if 就不会像你想要的那样工作。
在编译器开始处理所有代码之前,预处理器与其名称非常相似。所以它只评估MACRO值和prprocessor定义。
答案 2 :(得分:0)
也许这个:
#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会更好)