Monday, 29 January 2018

Template instantiation in GNU C++ and Clang



Looks like the rules for template instantiation in Clang (3.8) and GNU C++ (4.9) are not the same. Here is an example:



#include 

template
class Assert {
Assert(); // private constructor for Assert

};

template <>
class Assert { // implicit public constructor for Assert
};

template
class A {
};


template
T foo(A) {
return T(N - 1);
}

template
T foo(A<0>) { // foo is not defined for N=0
Assert();
return T(0);
}


int main(int argc, char **argv) {
foo(A<3>());
return 0;
}


This minimal example shows a template function, foo, that is generalized over a type T and a natural number N. This function is not defined for N=0, so I'd like to use the Assert class to signal a compiler error if it is used this way.



This code is accepted by the GNU compiler (and by Visual C++ 2015, as well), but Clang gives an error for "calling a private constructor of class Assert".




So who is right? As I see it, there is no call for foo, so there is no need to instantiate this template...



EDIT: Accepting Clang's interpretation of the standard, what is a canonical way to enforce compile-time checks on template parameters?


Answer



I believe clang is correct, since Assert is not a dependent type.



http://en.cppreference.com/w/cpp/language/dependent_name





Non-dependent names are looked up and bound at the point of template definition. This binding holds even if at the point of template instantiation there is a better match:




Don't make specializations that cannot be valid. Make them general purpose and use static_assert (with a dependent value) to check for invalid template argument types/values. static_assert(std::is_same::value) or static_assert(N != 0)


No comments:

Post a Comment

casting - Why wasn&#39;t Tobey Maguire in The Amazing Spider-Man? - Movies &amp; TV

In the Spider-Man franchise, Tobey Maguire is an outstanding performer as a Spider-Man and also reprised his role in the sequels Spider-Man...