Шаблон функции не может определить тип, если типы T и U совпадают

Этот вопрос связан с ответом, который я получил вчера. Для следующей функции я получаю ошибку couldn't deduce template parameter ‘V’ если оба T а также U являются std::complex<double>, Если T а также U отличаются, функция компилируется и работает как задумано.

template<class T, class U, class V>
auto operator*(const T a, const matrix<U> A) -> decltype(std::declval<T>()*std::declval<U>())
{
    matrix<V> B(A.size(1),A.size(2));
    for(int ii = 0; ii < B.size(1); ii++)
    {
        for(int jj = 0; jj < B.size(2); jj++)
        {
            B(ii,jj) = a*A(ii,jj);
        }
    }
    return B;
}

Использование заключается в следующем:

std::complex<double> a1;
matrix<std::complex<double> > A1;
double a2;
matrix<std::complex<double> > A2;

/* ... */

matrix<std::complex<double> > B1 = a1*A1; // Compiler error
matrix<std::complex<double> > B2 = a2*A2; // Compiles and runs fine.

Я должен также упомянуть, что я компилирую с включенным g++ 4.7.3 и C++11.

РЕДАКТИРОВАТЬ:

Обход, который я нашел, состоит в том, чтобы также предоставить этот шаблон функции:

template<class T>
matrix<T> operator*(const T a, const matrix<T> A)
{
    matrix<T> B(A.size(1),A.size(2));
    for(int ii = 0; ii < B.size(1); ii++)
    {
        for(int jj = 0; jj < B.size(2); jj++)
        {
            B(ii,jj) = a*A(ii,jj);
        }
    }
    return B;
}

С этим дополнением оба приведенных выше случая компилируются и работают правильно.

3 ответа

Решение

Я думаю, что должна быть еще одна перегрузка operator* участвует, потому что V не может быть выведено с учетом декларации:

template<class T, class U, class V>
auto operator*(const T a, const matrix<U> A)
  -> decltype(std::declval<T>()*std::declval<U>());

Единственный способ вызвать эту функцию - указать V явно, например, operator*<int, long, long>(...),


Изменить: глядя на подпись для operator*(T, matrix<T>) во втором примере кода может показаться, что ваш первый пример кода должен выглядеть так:

template<class T, class U>
auto operator*(const T a, const matrix<U>& A) -> matrix<decltype(a*A(0,0))>
{
    matrix<decltype(a*A(0,0))> B(A.size(1),A.size(2));
    for(int ii = 0; ii < B.size(1); ii++)
    {
        for(int jj = 0; jj < B.size(2); jj++)
        {
            B(ii,jj) = a*A(ii,jj);
        }
    }
    return B;
}

operator*(T,matrix<T>) не должно быть необходимым в качестве особого случая.

Проблема не в том T а также U те же, но в прототипе функции есть упоминание о V тип.

Учитывая, что вы используете V чтобы объявить B, что вы возвращаете, и что вы определяете тип возвращаемого значения как T()*U(), мне интересно, что matrix<V> должно быть.

Я ожидаю, что B и тип возвращаемого значения будет matrix<decltype(declval<T>()*declval<U>())>без V (этого не должно быть в списке параметров)

Я думаю, что если T и U различны, то вызывается другая функция, потому что компилятор прав, V не может быть выведен, точка. Даже я не могу понять, что вы думаете, этот параметр должен быть. Вот доказательство того, что второй также не компилируется и не запускается, что означает, что в этом случае вызывается другая функция. Очевидное решение состоит в том, чтобы просто удалить class V тип параметра шаблона, и просто используйте выведенный тип. Может быть, вы хотели что-то подобное?

Глядя на ваш код еще раз, тот, который вы говорите, терпит неудачу, complex * matrix в то время как второй matrix*matrix, что другое operator* определены?


Несвязанные, три нормальных способа принять параметры T, const T&, или же T&&, Там очень мало причин иметь const T тип параметра. Я полагаю, что вам не хватает &?

Другие вопросы по тегам