[C++]Как написать шаблон?
Нафига члены-то новым типом F параметризовать?
Чтобы складывать complex<double> и complex<int>? Хотя, наверное, правильнее будет определить соответствующий конструктор.
Хз почему, но у меня твой код работает (если дописать типы возвращаемых значений и прочую неинтересную ерунду):
Хз почему, но у меня твой код работает (если дописать типы возвращаемых значений и прочую неинтересную ерунду):
template <typename R>
class complex {
public:
R r, i;
complex(R r_, R i_) : r(r_ i(i_) {}
complex : r(0 i(0) {}
template <typename F> complex<R> operator+(complex<F> &b) {
return complex<R>(r + b.r, i + b.i);
}
template <typename F> complex<R> operator+(F b) {
return complex<R>(r + b, i);
}
};
int main(void) {
complex<double> a, b;
complex<int> c, d;
double e;
int f;
a = a + b;
c = c + d;
c = c + a;
a = a + c;
a = b + e;
c = d + f;
}
А ты чем собираешь?
У меня gcc version 4.0.1 (Apple Inc. build 5465 собирается тоже.
template <class T> class complex{
private:
T re_, im_;
public:
complex{}
complex(T re, T im): re_(re im_(im){}
template <class F> complex<T> operator+(const complex<F> &other)
{
return complex(re_ + other.re_, im_ + other.im_);
}
template <class F> complex<T> operator+(const F &other)
{
return complex(re_ + other, im_);
}
};
void f
{
complex<double> a, b;
a = a + b;
}VS 2008, компилируется.
gcc 4.3.2
А кто-нибудь может объяснить почему в этом коде
компилятор (проверял на gcc и comeau online) выбирает второй operator+, а если заменить тип параметра на константную ссылку, то выбирает первый?
template <class T> class complex{
private:
T re_, im_;
public:
complex{}
complex(T re, T im): re_(re im_(im){}
template <class F> complex<T> operator+(const complex<F> &other)
{
return complex(re_ + other.re_, im_ + other.im_);
}
template <class F> complex<T> operator+(F &other)
{
return complex(re_ + other, im_);
}
};
int main
{
complex<double> a, b;
a = a + b;
}
компилятор (проверял на gcc и comeau online) выбирает второй operator+, а если заменить тип параметра на константную ссылку, то выбирает первый?
омпилятор (проверял на gcc и comeau online) выбирает второй operator+быть такого не может
быть такого не можетtest.cpp:
#include <iostream>
template <class T> class complex{
private:
T re_, im_;
public:
complex{}
complex(T re, T im): re_(re im_(im){}
template <class F> complex<T> operator+(const complex<F> &other)
{
return complex(re_ + other.re_, im_ + other.im_);
}
template <class F> complex<T> operator+(F &other)
{
std::cout << "Ooops!" << std::endl;
// return complex(re_ + other, im_);
}
};
int main
{
complex<double> a, b;
a = a + b;
}
mutant ~ $ g++ test.cpp
mutant ~ $ ./a.out
Ooops!
Разъясните двоечнику как это работает, пожалуйста.
Сам разобрался.
Автор, верни возвращение комплекса, тогда код не будет компилироваться, т.к. не будет констуктора complex(complex, double). Без него второй вариант подходит лучше, т.к. в нём не нужно кастить к константному объекту.
Сам разобрался.
Автор, верни возвращение комплекса, тогда код не будет компилироваться, т.к. не будет констуктора complex(complex, double). Без него второй вариант подходит лучше, т.к. в нём не нужно кастить к константному объекту.
На самом деле, если там раскомментировать return, то код не будет компилироваться уже из-за того, что не найдется operator+(double, complex до конструктора дело даже не дойдет.
А вот про то, что при выборе перегрузки константность аргумента важнее его типа я не знал
А вот про то, что при выборе перегрузки константность аргумента важнее его типа я не знал

А вот про то, что при выборе перегрузки константность аргумента важнее его типа я не зналА тут уже ты не понял. Во второй перегрухке он считает, что F == complex<double> и потому что complex<double> & - ближе к complex<double>, чем const complex<double> &
Да, верно. Что-то я ступил 

вынеси оператор из класса и специализируй его:
PS. передача параметров по ссылке тоже компилируется.
PSS. gcc version 4.2.3
[xoft ~]$ cat xxx.cpp
#include <iostream>
using namespace std;
template <class R> struct complex {
complex(R x, R y): x(x y(y) {}
R x;
R y;
};
template <class R, class F>
complex<R> operator+(complex<R> z1, F x2) {
cout << "operator+(complex<R> z1, F x2)" << endl;
return complex<R>(z1.x+x2, z1.y);
}
template<class R, class F>
complex<R> operator+(complex<R> z1, complex<F> z2) {
cout << "operator+(complex<R> z1, complex<F> z2)" << endl;
return complex<R>(z1.x+z2.x, z1.y + z2.y);
}
int main {
complex<double> c(0.5, 0.6);
c + 1;
c + c;
return 0;
}
[xoft ~]$ ./xxx
operator+(complex<R> z1, F x2)
operator+(complex<R> z1, complex<F> z2)
PS. передача параметров по ссылке тоже компилируется.
PSS. gcc version 4.2.3
template <typename F> operator+(complex<F> &b);Вообще старайся писать более общие варианты перед узкоспециализированными.
template <typename F> operator+(F b);
=) это лишь особенность мышления css+xslt программистов, не более 

Это хаскель - там более общие идут после тех, что уже. Имхо, так логичнее.
ну я про это и говорил, в хаскеле и похожих языках частное пишут вверху, потому что как бы подразумевается if/elseif/elseif/..., а в css и в xslt пишут общее вверху, подразумевая override-ы. и так и так логично выглядит, не надо из этого каких-то фундаметнальных выводов делать
но мне кстати xslt-шный стиль симпатишнее кажется, он применим и при отсутствии локальности, написал override в основной программе и не надо париться, есть какое-то более общее определение в какой-нибудь используемой библиотеке или нет.
но мне кстати xslt-шный стиль симпатишнее кажется, он применим и при отсутствии локальности, написал override в основной программе и не надо париться, есть какое-то более общее определение в какой-нибудь используемой библиотеке или нет.=) это лишь особенность мышления css+xslt программистов, не болееВовсе нет, просто специализации шаблонов обязаны идти после описаний более общих определений.
Оставить комментарий
apl13
Забавная такая проблема. Решил, для примера, сделать комплексные числа. Пишуtemplate <typename R> complex {template <typename F> operator+(complex<F> &b);
template <typename F> operator+(F b);
}
, имея в виду, что одно дело - прибавить к комплексному числу комплексное число, другое дело - прибавить к нему же число вещественное.
Компилятор, встретив
не знает, какой из вариантов сложения взять.
А я не знаю, что ему посоветовать.
Тут можно что-нибудь сделать?