Перегрузка оператора через функцию Friend и возвращение типа, отличного от параметров rhs.

Я прилагаю код здесь и объясняю проблему ниже:
Вот класс Битоп:

#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. Но я получаю ошибку компиляции (из-за переопределения) независимо от того, вызываю ли я функцию «+».

Мне не ясно, что я здесь делаю неправильно. Любая помощь приветствуется.

Обратите внимание, что я оставил несколько функций и вызовов функций в коде, чтобы гарантировать корректную работу других перегрузок, таких как = и + =.

0

Решение

Вот упрощенный пример, который показывает ту же проблему:

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;
}
0

Другие решения

Вам не нужно определять 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),

0

По вопросам рекламы [email protected]