【问题标题】:Overloaded function candidate matching problems重载的候选函数匹配问题
【发布时间】:2013-08-03 05:48:38
【问题描述】:

我不确定我是否理解这里发生的事情的细微差别,并希望得到解释。

我正在从模板化包装器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&lt;float, float&gt;(...) 然后执行typeid 比较if (typeid(DType) == typeid(CType))... 我会得到预期的答案吗?现在看来,并非如此。如何正确检查模板类型以进行此比较?

【问题讨论】:

  • 函数正在等待 nm::Complex64* 但您正在传递 float*
  • 看第一个函数定义。那就是... 1) 接受 14 个参数 2) 接受所有 float* 而不是任何 nm::Complex64*
  • 我假设你想调用第二个函数,因为你传递了 15 个参数。 (注:候选人期望 14 个参数,提供 15 个)
  • 好点...我想你可能已经明白了。我现在怀疑这是我对DTypeCType 的比较。如果我用所有浮点数调用 15 参数版本,那就错了。完美。
  • 这表明我的比较应该有效...java2s.com/Tutorial/Cpp/0100__Development/…

标签: c++ templates overloading typeid


【解决方案1】:

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
}

为什么会这样

编译器替换编译时指定的类型。这样,如果你用 初始化,它会用 float 改变 if

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 的类型是浮点数。 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)。

【讨论】:

  • typeid(double) == typeid(double) 不应为假。此外,里面的代码在模板之前编译和运行。
  • 问题是编译器会改变float的CType。之后会尝试编译代码。
  • 为了让您看到typeid(double) == typeid(double) 不是问题,您可以尝试将if 更改为if(true) 看看会发生什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-09
  • 1970-01-01
  • 2011-01-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多