Я прилагаю код здесь и объясняю проблему ниже:
Вот класс Битоп:
#ifndef _Bitop_H
#define _Bitop_H
# include <iostream>
double num2fxp(double v, int bits=9, int intbits=5){
return -0.5;
}
template<int bits = 8, int intbits = 6>
class Bitop
{
template<int rhsbits, int rhsintbits> friend class Bitop;
private:
double value; // data value
public:
Bitop(const double& v=0):
value(num2fxp(v, bits, intbits))
{}
template<int rhsbits, int rhsintbits>
const Bitop<bits, intbits>& operator = (const Bitop<rhsbits, rhsintbits>& v){
value = num2fxp(v.value, bits, intbits);
return *this;
}
template<int rhsbits, int rhsintbits>
Bitop<bits, intbits>& operator += (const Bitop<rhsbits, rhsintbits>& v) {
value = num2fxp(value+v.value, bits, intbits);
return *this;
}
template<int lhsbits, int lhsintbits, int rhsbits, int rhsintbits>
friend Bitop<lhsintbits+rhsintbits+2, lhsintbits+rhsintbits+1> operator + (const Bitop<lhsbits, lhsintbits>& x, const Bitop<rhsbits, rhsintbits>& y){
return Bitop<lhsintbits+rhsintbits+2, lhsintbits+rhsintbits+1> (num2fxp(x.value+y.value));
}
friend std::ostream& operator<< (std::ostream & out, const Bitop& y){return out << y.value ;}
void Print(){
std::cout << value<< "<"<< bits << ","<< intbits << ">";
}
};
#endif
И функция теста:
# include <iostream>
# include "Bitop.H"
using namespace std;
int main (int argc, char** argv) {
Bitop<4,1> a = 0.8;
Bitop<5,2> b(3.57);
Bitop<7,3> c;
c = b;
cout << "See all attributes of c \n";
c.Print();cout << "\n";
c = 7.86;
cout << "reassign c to a new value\n";
c.Print();cout << "\n";
cout << "set b = c \n";
b = c;
b.Print();cout<<"\n";
cout << "set b+=a \n";
b += a;
b.Print();cout<<"\n";
cout << "set b=c+a \n";
b = c+a;
b.Print();cout<<"\n";
return 0;
}
У меня есть шаблонный класс Битоп. Я хочу перегрузить «+», чтобы добавить 2 объекта с различными параметрами шаблона и вернуть третий объект с параметрами, отличными от объектов rhs и lhs, т.е. я хочу сделать следующее:
Bitop<5,3> + Битоп<4,2> должен вернуть битоп<10,6>. Я объявил Bitop своим классом-другом, чтобы иметь доступ к закрытым членам объектов rhs и lhs. Но я получаю ошибку компиляции (из-за переопределения) независимо от того, вызываю ли я функцию «+».
Мне не ясно, что я здесь делаю неправильно. Любая помощь приветствуется.
Обратите внимание, что я оставил несколько функций и вызовов функций в коде, чтобы гарантировать корректную работу других перегрузок, таких как = и + =.
Вот упрощенный пример, который показывает ту же проблему:
template<int i>
struct X {
template<int a, int b>
friend void foo(X<a>, X<b>) { }
};
int main()
{
X<1> x1;
X<4> x2; // error: redefinition of foo
}
Каждый раз новая специализация X
получает конкретизацию, определение foo
вставляется в область видимости шаблона класса X
, Надеюсь, понятно, откуда исходит ошибка.
Все было бы иначе, если бы объявление зависело от параметра шаблона класса, например:
template<int i>
struct X {
template<int a, int b>
friend void foo(X<a+i>, X<b+i>) { } // different definiton
// for each specialization of X
};
Решение состоит в том, чтобы определить функцию друга вне класса:
template<int i>
struct X {
template<int a, int b>
friend void foo(X<a>, X<b>);
};
template<int a, int b>
void foo(X<a>, X<b>) { }
int main()
{
X<1> x1;
X<4> x2;
}
Вам не нужно определять operator+
как друг:
template<int I>
class A
{
double X;
template<int> friend class A;
public:
A(A const&) = default;
A(double x)
: X(x) {}
template<int J>
A(A<J> const&a)
: X(a.X) {}
template<int J>
A<I+J> operator+ (A<J> const&a)
{ return A<I+J>(X+a.X); }
};
int main()
{
A<0> a0(3);
A<1> a1(4);
auto ax = a0+a1;
}
Более того, результат, возвращаемый operator+(a,b)
действительно должен быть идентичен полученному operator=(a)
с последующим operator+=(b)
,