Смешанная арифметика и friend вне шаблона класса

184
15 декабря 2016, 16:09

Здравствуйте!

Хочу вынести friend-функцию оператора за определение класса:

template<typename T>
class A;
template <typename T>
const A<T> operator + (A<T> a, const A<T>& b);
template <typename T>
class A {
...
public:
    A(){...}
    A(T t){...}
    const A& operator += (const A& r);
    friend const A operator + <T> (A a, const A& b);
};
template <typename T>
const A<T>& A<T>::operator += (const A<T>& r) {...}
template <typename T>
const A<T> operator + (A<T> a, const A<T>& b) {
    return a += b;
}

Однако с этим кодом проблема: A<int> += 1 работает, а вот A<int> + 1 — нет:

int main() {
    A<int> (1) += 2;  // Ok
    A<int> (1) + A<int> (2);  // Ok
    A<int> (1) + 2;  // Error!
    return 0
}

Т. е. смешанная арифметика не работает. Вопрос — почему, и как правильно ее сделать?

Answer 1

Кажется, я нашел причину.

При вызове шаблонной функции не происходит приведения типов:

Если вызвать обычную функции с сигнатурой, к примеру, int a(int, int), то компилятор попытается привести все операнды к инту.

Если же вызвать шаблон с сигнатурой <T> b(<T>, <T>) от разных типов (b(int_val, double_val), к примеру), то возникает проблема: каким типом считать <T>? Приводить ли int_val к типу double_val, или наоборот.

Если же внести friend функцию внутрь класса, такой проблемы не происходит:

template <typename T>
class A {
...
public:
    A(){...}
    A(T t){...}
    const A& operator += (const A& r);
    friend const A operator + <T> (A a, const A& b) {
        return a += b;
    }
};
Answer 2

Во-первых, у вас класс недописанный, а во-вторых, своему типу при объявлении нужно дать имя (нельзя тип складывать с другим типом, складывают объекты). См.:

int main(){
    A<int> theA(1);  // здесь есть имя а ниже нет!
    //A<int> (1) + A<int> (2);  // Ok
    //A<int> (1) + 2;  // Error!
    return 0;
}

См. ещё:

int main(){
        A<int> theA(1), theB(5);  // здесь есть имя!
        A<int> theC = theA + theB;  // вот так выполняют сложение
        return 0;
    }
READ ALSO
Повторный запуск программы

Повторный запуск программы

При повторном запуске результаты поиска не выводятся и не записываются в файлПри первичном все работает

176
Пример реализации классов в UML для C++ кода

Пример реализации классов в UML для C++ кода

Вот что написано: реализация – это способ показать наследование интерфейса в UMLКогда мы говорим, что класс A реализует интерфейс B, это значит,...

209
Как узнать адрес начала массива в ассемблере?

Как узнать адрес начала массива в ассемблере?

Нужно с использованием оператора LEA узнать адрес начала списка символов, чтобы потом с помощью XLAT выбрать нужный символС обычной переменной...

283
-1.#IND  без деления на 0

-1.#IND без деления на 0

Прочитал, что такая ошибка при делении на ноль, но у меня нет никакого деления, самая простая программа:

264