Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

candidate template ignored: substitution failure(error with clang but not g++)

I have a problem of substitution failure, and answers of some similar questions do not help me.

Here is the code:

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)
    {
       // ...
    }
    // ...
};

And I call this template function like so:

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

Using g++, it compiles.

When using clang++(linux) to compile(clang++ -std=c++11 xxx.cpp), it resulted in the following compiling error:

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)

Why?

like image 642
Shindou Avatar asked Jul 22 '15 10:07

Shindou


1 Answers

It's a bug in clang; it misbehaves when an alias template defining an array type is defined within a class template. In fact it can be exploited to crash the compiler:

template<int I>
struct S {
  template<int J> using T = int[J];
  using U = T<I>;
};
S<3>::U a;

Since in your case Reference::matrix_t does not depend on the template arguments to Reference, the simplest workaround would be to move the definition of matrix_t to namespace scope:

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>;

In fact, you don't even need to use impl::matrix_t to workaround the bug:

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!

This is now fixed (the fix should be in clang release version 3.8.0):

[AST] Perform additional canonicalization for DependentSizedArrayType

We treated DependentSizedArrayTypes with the same element type but differing size expressions as equivalently canonical. This would lead to bizarre behavior during template instantiation.

This fixes PR24212.

like image 165
ecatmur Avatar answered Sep 25 '22 06:09

ecatmur