候选模板被忽略:替换失败(clang但不是g ++错误)

Shi*_*dou 9 c++ templates g++ clang c++11

我有一个替换失败的问题,一些类似问题的答案对我没有帮助.

这是代码:

template<int dim, int loop>  
class Reference{
public:
   //...
   template<int r, int c> using matrix_t = int[r][c];
   Reference(const matrix_t<dim, loop> &mat){}
}; 

template<int dim, int loop>
class Partition{
    // ...
public:
    // ...
    template<int r, int c> using matrix = int[r][c];
    template<int r, int c> void readPattern(const matrix<r,c> &pattern)
    {
       // ...
    }
    // ...
};
Run Code Online (Sandbox Code Playgroud)

我称这个模板函数如下:

int main()
{
   // ... 
   const int DENOISE_UR[3][4] = {/*...*/};
   Partition<1,2> partition;
   partition.readPattern(DENOISE_UR);
   // ...
}
Run Code Online (Sandbox Code Playgroud)

使用g ++编译.

当使用clang ++(linux)编译(clang++ -std=c++11 xxx.cpp)时,它导致以下编译错误:

error: no matching function for call to 'readPattern'
   note: candidate template ignored: substitution failure[ with r = 3, c = 4 ]
         template<int r, int c> void readPattern(const matrix<r,c> &pattern)
Run Code Online (Sandbox Code Playgroud)

为什么?

eca*_*mur 5

这是叮当中的错误;当在类模板中定义了定义数组类型的别名模板时,它的行为不正确。实际上,它可以被利用来使编译器崩溃

template<int I>
struct S {
  template<int J> using T = int[J];
  using U = T<I>;
};
S<3>::U a;
Run Code Online (Sandbox Code Playgroud)

由于您的情况Reference::matrix_t不依赖于的模板参数Reference,最简单的解决方法是将的定义matrix_t移至名称空间范围:

namespace impl { template<int r, int c> using matrix_t = int[r][c]; }
// ...
template<int dim, int loop>  
class Reference {
  //...
  template<int r, int c> using matrix_t = impl::matrix_t<r, c>;
Run Code Online (Sandbox Code Playgroud)

实际上,您甚至不需要使用 impl::matrix_t解决此错误的方法:

namespace magic { template<int r, int c> using unused = int[r][c]; } // Huh?
// ...
template<int dim, int loop>  
class Reference {
  //...
  template<int r, int c> using matrix_t = int[r][c]; // Look ma, no hands!
Run Code Online (Sandbox Code Playgroud)

现在,此问题已修复(此修复程序应该在clang发行版3.8.0中):

[AST]对DependentSizedArrayType执行其他规范化

我们将具有相同元素类型但大小表达式不同的DependentSizedArrayTypes视为等效规范。这将导致模板实例化过程中的异常行为。

这修复了PR24212。