Перегрузка функции, возвращающей вектор, чтобы она могла возвращать вектор другого типа

У меня неоднократно возникала эта проблема в моем коде (и теперь я думаю, что ее невозможно обойти): по какой-то причине, когда я пытаюсь написать метод, который возвращает std::vector<long double>, и пытаюсь перегрузить его с тем же именем метода, что и возвращает другой std::vector, скажем, std::vector<std::complex<long double> >, я получаю сообщение об ошибке, похожее на: std::vector<std::vector<long double> > cannot be overloaded with std::vector<long double>, хотя я включил необходимые классы #include. Почему это?? Есть ли в этом какое-то обоснование??

Вот код, имитирующий проблему:

#ifndef MATRIXALGORITHMS_H
#define MATRIXALGORITHMS_H
#include <complex>
#include <vector>

class MatrixAlgorithms
{
    public:
        MatrixAlgorithms();
        //two algorithms that are not strictly for matrices; they are for solving quadratic and cubic polynomials
        //quadratic method; the roots might be real, so there should be two versions of this algorithm
        std::vector<long double> quadraticFormula(long double, long double, long double);
        std::vector<std::complex<long double> > quadraticFormula(long double, long double, long double);
    protected:
    private:
};

#endif // MATRIXALGORITHMS_H

Я попытался скомпилировать его, и он дал мне вышеупомянутую ошибку....


person Mike Warren    schedule 01.01.2014    source источник


Ответы (4)


Тип возврата метода не используется в разрешении перегрузки.

Почему ? Причин много, но самая простая заключается в том, что вы не сможете угадать, какая функция вызывается, когда возвращаемое значение игнорируется, что совершенно законно.

E.g.:

int f();
double f();


f(); // Which one would you call ?

Можно легко найти и другие, более сложные причины:

int f();
double f();

void g(int);
void g(double);

g(f()); // Which f and g do you call ?

Не говоря уже о auto и так далее...

person Johan    schedule 01.01.2014
comment
Я понял теперь; // Думаю, мне нужен был пример, независимый от того, над чем я работал... - person Mike Warren; 02.01.2014
comment
Кроме того, я обнаружил, что в моем случае не было веской причины для перегрузки; // так как действительное число ЯВЛЯЕТСЯ комплексным числом с мнимой частью нуля /*Я мог бы просто вернуть std::vector<std::complex<long double> > и проверить, если Im(roots[index]) == 0 */ - person Mike Warren; 02.01.2014

Тип возвращаемого значения не участвует в разрешении перегрузки.

person Vlad from Moscow    schedule 01.01.2014
comment
Я думал, что вопрос был в том, почему это так. - person juanchopanza; 02.01.2014
comment
Это так, так что это не отвечает на вопрос. - person Lightness Races in Orbit; 02.01.2014

Тип возвращаемого значения не является частью сигнатуры функции. Это не имеет особого смысла. Как вы ожидаете, что вывод типа будет работать, когда изменяется только тип возвращаемого значения? то есть:

auto func = ambiguous(0.0, 0.0, 0.0); // Which one to use?

Вы можете указать выходной параметр. Это распространенная идиома в Microsoft:

quadraticFormula(long double, long double, long double, TypeOne& out);

Хотя это потребует от ваших пользователей полагаться на Intellisense или документацию. Другой вариант — переименовать ваши functions.

quadraticFormulaOne(...);
quadraticFormulaTwo(...);

Но это может раздражать, если их много.


C++ (подраздел 7.4.1 Бьерна Страуструпа «Язык программирования C++»): «Типы возвращаемых значений не учитываются при разрешении перегрузки. Причина в том, чтобы сохранить разрешение для отдельного оператора или вызова функции независимо от контекста. Учтите:

float sqrt(float);
double sqrt(double);

void f(double da, float fla)
{
    float fl = sqrt(da);     // call sqrt(double)
    double d = sqrt(da); // call sqrt(double)
    fl = sqrt(fla);            // call sqrt(float)
    d = sqrt(fla);             // call sqrt(float)
}

Если бы учитывался тип возвращаемого значения, было бы невозможно рассматривать вызов sqrt() изолированно и определять, какая функция была вызвана».

Подробное обсуждение см. в разделе Перегрузка функций по типу возвращаемого значения?.

person Community    schedule 01.01.2014

Это не имеет ничего общего с вектором; вы не можете перегружать тип возвращаемого значения.

[C++11: 13.1/2]: Некоторые объявления функций не могут быть перегружены:

  • Объявления функций, отличающиеся только типом возвращаемого значения, не могут быть перегружены.
  • [..]

Что касается обоснования: как компилятор узнает, какую функцию вы хотели вызвать? Он может выбирать только на основе аргументов, которые вы ему даете.

Ваше ожидание похоже на поход в ресторан и начало следующего взаимодействия:

<mike_warren> Добрый вечер. Пожалуйста, мне мое любимое блюдо.
<waiter> Какое ваше любимое блюдо, сэр?
<mike_warren> Эта информация вам недоступна.
<waiter> Не могли бы вы дать какие-либо подсказки или советы, которые могут помочь мне определить какую еду вы хотели бы подать?
<mike_warren> Нет, извините. Вы узнаете, какая у меня любимая еда, только после того, как вы ее подали.
<waiter> Сэр, это не имеет особого смысла. Я не могу подать ваше любимое блюдо, не зная заранее, что это такое. Только из этой информации шеф-повар узнает, как приготовить ваше блюдо.
<mike_warren> Тогда, я думаю, у нас проблемы.
<waiter> Уходите, пока я не вызвал полицию.

person Lightness Races in Orbit    schedule 01.01.2014