Проблемы соответствия кандидатов перегруженных функций

Я не уверен, что понимаю нюанс происходящего здесь и надеялся на объяснение.

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

inline void lapack_gesvd(char *jobu, char *jobvt,
int *m, int *n,
float *a, int *lda,
float *s,
float *u, int *ldu,
float *vt, int *ldvt,
float *work,  int *lwork,
int *info) {
sgesvd_(jobu, jobvt, m, n,
a, lda, s, u, ldu,
vt, ldvt, work, lwork,
info);
}
inline void lapack_gesvd(char *jobu, char *jobvt,
int *m, int *n,
nm::Complex64 *a, int *lda,
nm::Complex64 *s,
nm::Complex64 *u, int *ldu,
nm::Complex64 *vt, int *ldvt,
nm::Complex64 *work,  int *lwork, float *rwork,
int *info) {
cgesvd_(jobu, jobvt, m, n,
a, lda, s, u, ldu,
vt, ldvt, work, lwork,
rwork, info);
}

Это работало до тех пор, пока я не объявил второй тип перегрузки (я перегрузил с помощью float и double, без проблем), но теперь он выдает несколько ошибок и, похоже, не учитывает мои аргументы.

Я вызываю это из функции, которая приняла аргументы как:

template <typename DType, typename CType>
static int lapack_gesvd_nothrow(char *jobu, char *jobvt,
int m, int n,
void *a, int lda,
void *s,
void *u, int ldu,
void *vt, int ldvt,
void *work,  int lwork,
int info, void *rwork) {
....
DType* UPCASE = reinterpret_cast<DType*>(lowercase);
....

if (typeid(DType) == typeid(CType)) {
lapack_gesvd(jobu, jobvt, &m, &n, A, &lda, S, U, &ldu, VT, &ldvt, WORK, &lwork, &info);
} else {
CType* RWORK = reinterpret_cast<CType*>(rwork);
lapack_gesvd(jobu, jobvt, &m, &n, A, &lda, S, U, &ldu, VT, &ldvt, WORK, &lwork, RWORK, &info);
}

Я буквально только делаю reinterpret_casts между двумя.

Вот fxn, который он явно ищет:

error: no matching function for call to ‘lapack_gesvd(char*&, char*&, int*, int*, float*&, int*, float*&, float*&, int*, float*&, int*, float*&, int*, float*&, int*)

А вот и кандидатские матчи:

candidates are:
note: void nm::math::lapack_gesvd(char*, char*, int*, int*, float*, int*, float*, float*, int*, float*, int*, float*, int*, int*)
note:    candidate expects 14 arguments, 15 provided
void nm::math::lapack_gesvd(char*, char*, int*, int*, double*, int*, double*, double*, int*, double*, int*, double*, int*, int*)
note:   candidate expects 14 arguments, 15 provided
void nm::math::lapack_gesvd(char*, char*, int*, int*, nm::Complex64*, int*, nm::Complex64*, nm::Complex64*, int*, nm::Complex64*, int*, nm::Complex64*, int*, float*, int*)
note:   no known conversion for argument 5 from ‘float*’ to ‘nm::Complex64* {aka nm::Complex<float>*}’

Я озадачен, почему разыменование появляется сейчас, когда кажется, что это требуется error: invalid conversion from 'int' to 'int*' без него, и требуется до этой самой последней перегрузки.

Ваши объяснения и решения будут наиболее ценными! Спасибо!

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

Это может сводиться к:

Если я позвоню lapack_gesvd_nothrow<float, float>(...) а затем выполнить сравнение typeid if (typeid(DType) == typeid(CType))… я получу ожидаемый ответ? Сейчас это не так. Как правильно проверить типы шаблонов для этого сравнения?

2

Решение

TL; DR

Вы делаете это:

if (false) {
// some language rule violation here
} else {
// correct code here
}

Обе стороны if-else должны быть компилируемыми.

Решение

Вы можете частично специализировать шаблон.

template <class U, class V>
void foo(...){
//assume U and V are different
}

template <class U>
void foo<U, U>(...){
//assume both types are the same
}

Почему это происходит

Компилятор подставляет тип, указанный во время компиляции. Таким образом, если вы инициализируете с помощью, это изменит if с помощью float

lapack_gesvd_nothrow<float, float>(...)

if (typeid(float) == typeid(float))

Таким образом, код в конечном итоге выглядит так:

if (typeid(float) == typeid(float)){
lapack_gesvd(jobu, jobvt, &m, &n, A, &lda, S, U, &ldu, VT, &ldvt, WORK, &lwork, &info);
} else {
CType* RWORK = reinterpret_cast<CType*>(rwork);
lapack_gesvd(jobu, jobvt, &m, &n, A, &lda, S, U, &ldu, VT, &ldvt, WORK, &lwork, RWORK, &info);
}

Компилятор увидит, что тип A является float. Первая часть оператора if-else будет правильной. Хотя во второй части нет. Вот пример того, как компилятор увидит это:

void foo(float, float){};
void foo(int, int, int){};
template <class U>(){
...
U a, b, c;
if (...)
foo(a, b);
else
foo(a, b, c);
...
}
//Will be changed to
float a, b, c;
if (...)
foo(a, b);
else
foo(a, b, c);

Результатом является ошибка компилятора в части else, потому что нет foo (float, float, float).

1

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

Других решений пока нет …

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