Fal*_* We 6 c++ gcc templates visual-studio
为什么下面的代码可以在 Visual Studio 2019 中编译,而不能在 gcc 8.3 中编译?
#include<array>
template<typename T> class myClass {
public:
template<unsigned int N> myClass(const std::array<T, N>& elems) { /* do something */ }
};
int main() {
std::array<int, 10> A;
myClass<int> Tabular(A);
}
Run Code Online (Sandbox Code Playgroud)
这是我从我学生的项目中提取的片段,因为对我来说它看起来很奇怪。我用 gcc 8.3 尝试这个,因为我怀疑编译器抱怨模板参数推导失败。所以我告诉我的学生这行不通。但是他认为这确实可以在 VS 中编译而没有警告,我查了一下,他是对的。
因为我离称自己为专家还很远,所以我无法向自己和我的学生解释是否/为什么/出了什么问题。
Gcc 和 MSVC 都是正确的。的第二个模板参数的std::array类型定义为std::size_t,如何std::size_t定义取决于实现。
Run Code Online (Sandbox Code Playgroud)typedef /*implementation-defined*/ size_t;
std::size_t是 sizeof 运算符结果的无符号整数类型as well as the sizeof... operator and the alignof operator (since C++11)。的位宽
std::size_t不小于 16。(C++11 起)
那么whenstd::size_t定义为和unsigned int代码一样编译就好了,否则会失败;类型不匹配导致非类型模板参数推导失败。
更改unsigned int为std::size_tthen 代码保证可以用任何像样的编译器很好地编译。例如
template<typename T> class myClass {
public:
template<std::size_t N> myClass(const std::array<T, N>& elems) { /* do something */ }
};
Run Code Online (Sandbox Code Playgroud)
以及为什么类型不匹配导致非类型模板参数推导失败。
(强调我的)
如果在形参列表中使用了非类型模板形参,并推导出了相应的模板形参,则所推导出的模板形参的类型(在其封闭的模板形参列表中指定,意味着保留引用)必须匹配非类型模板参数完全,除了 cv 限定符被删除,除了模板参数是从数组中推导出来的——在这种情况下,任何整数类型都是允许的,即使 bool 总是会变为真:
Run Code Online (Sandbox Code Playgroud)template<int i> class A { }; template<short s> void f(A<s>); // the type of the non-type template param is short void k1() { A<1> a; // the type of the non-type template param of a is int f(a); // P = A<(short)s>, A = A<(int)1> // error: deduced non-type template argument does not have the same // type as its corresponding template argument f<1>(a); // OK: the template argument is not deduced, // this calls f<(short)1>(A<(short)1>) } template<int&> struct X; template<int& R> void k2(X<R>&); int n; void g(X<n> &x) { k2(x); // P = X<R>, A = X<n> // parameter type is int& // argument type is int& in struct X's template declaration // OK (with CWG 2091): deduces R to refer to n }