[英]As template type argument, why doesn't type[N] match its specialized version -— template<class T> class S<T[]>
Here is a demo (shortened from cppreference ): 这是一个演示(缩写为cppreference ):
#include <iostream>
#include <type_traits>
template<class T>
struct is_array : std::false_type {};
template<class T>
struct is_array<T[]> : std::true_type {};
class A {};
int main()
{
std::cout << std::boolalpha;
std::cout << is_array<A>::value << '\n';
std::cout << is_array<A[]>::value << '\n';
std::cout << is_array<A[3]>::value << '\n';
}
output( live demo
): 输出(
live demo
):
false
true
false
We can see that is_array<A[3]>
is resolved as the primary specialization: template<class T> struct is_array
, and not template<class T> struct is_array<T[]>
. 我们可以看到
is_array<A[3]>
被解析为主要特化: template<class T> struct is_array
,而不是template<class T> struct is_array<T[]>
。
It confuses me a fair bit. 这让我很困惑。 Of course I know the complete implementation of
std::is_array
(as documented in cppreference) also contains a specialization for length: template<class T, std::size_t N> struct is_array<T[N]>
, and std::is_array<A[3]>
will resolve to this specialization as expected. 当然我知道
std::is_array
的完整实现(如cppreference中所述)还包含length的特殊化: template<class T, std::size_t N> struct is_array<T[N]>
和std::is_array<A[3]>
[3]>将按预期解决此专业化问题。 But that cannot explain the uppermost demo, right? 但这无法解释最重要的演示,对吧?
After searching, I found this thread , but it is a question about how , not why . 搜索之后,我找到了这个帖子 ,但这是一个关于如何 ,而不是为什么的问题 。 But in a comment , @Steve Jessop mentioned:
但在评论中 , @ Steve Jessop提到:
I'm not entirely sure, but I think what you've written there is a specialization for arrays of unknown size.
我不完全确定,但我认为你在那里写的是对未知大小的数组的专门化。 That's an incomplete type, but can be used in an extern declaration of an array that some other TU will provide.
这是一个不完整的类型,但可以用于其他TU将提供的数组的extern声明。
It seems to related to it being an incomplete type : 它似乎与它是一个不完整的类型有关 :
The declared type of an array object might be an array of unknown bound and therefore be incomplete at one point in a translation unit and complete later on;
声明的数组对象类型可能是未知边界的数组,因此在翻译单元中的某个点处不完整,稍后会完成; the array types at those two points (“array of unknown bound of T” and “array of NT”) are different types.
这两个点的数组类型(“T的未知边界数组”和“NT数组”)是不同的类型。 The type of a pointer to array of unknown bound, or of a type defined by a typedef declaration to be an array of unknown bound, cannot be completed
指向未知边界数组的指针类型,或者由typedef声明定义为未知边界数组的类型的指针类型无法完成
extern int arr[]; // the type of arr is incomplete
int arr[10]; // now the type of arr is complete
[basic.types]/6 doesn't offer any other useful information about this. [basic.types] / 6没有提供任何其他有用的信息。
I noticed an error in the sample from the spec, which got me thinking that maybe it is not about specialization, but because A[3]
cannot match struct is_array<T[]>
. 我注意到规范中的示例中有一个错误,这让我想到它可能不是关于特化,而是因为
A[3]
不能匹配struct is_array<T[]>
。 That's what the compiler seems to affirm: 这就是编译器似乎肯定的:
#include <iostream>
#include <type_traits>
template<class T>
struct is_array<T[]> : std::true_type {};
class A {};
int main()
{
is_array<A[3]> *a; // error
is_array<A[3]> b; // error
}
Above is what I tried to solve this by myself, without success. 以上是我自己试图解决的问题,没有成功。 So I am here to find a thorough answer.
所以我在这里找到一个彻底的答案。
The short answer is in the paragraph you quoted yourself: 简短的回答在你自己引用的段落中:
The declared type of an array object might be an array of unknown bound and therefore be incomplete at one point in a translation unit and complete later on;
声明的数组对象类型可能是未知边界的数组,因此在翻译单元中的某个点处不完整,稍后会完成; the array types at those two points (“array of unknown bound of T” and “array of NT”) are different types .
这两个点的数组类型(“T的未知边界数组”和“NT数组”)是不同的类型 。 The type of a pointer to array of unknown bound, or of a type defined by a typedef declaration to be an array of unknown bound, cannot be completed
指向未知边界数组的指针类型,或者由typedef声明定义为未知边界数组的类型的指针类型无法完成
Those are different types. 那些是不同的类型。 While you may "fix" the type of an array object after the first point of declaration, it still doesn't change the fact those are different types.
虽然您可以在第一个声明点之后“修复”数组对象的类型,但它仍然不会改变那些不同类型的事实。 They behave differently.
他们的行为不同。 For instance:
例如:
using AI = int[];
using AC = int[3];
AI a1 = {1, 2, 3, 4};
AC a2 = {1, 2, 3, 4}; // error
The object a1
can be initialized with the initializer {1, 2, 3, 4}
. 可以使用初始化程序
{1, 2, 3, 4}
初始化对象a1
。 We see that the type I aliased as AI
kinda behaves like auto
, an initializer can be used to help deduce the complete type. 我们看到I类型别名为
AI
有点像auto
,初始化器可用于帮助推断完整类型。
On the other hand, a2
causes an error, because I provided too many initializers. 另一方面,
a2
导致错误,因为我提供了太多的初始化器。 And if I were to provide too few, I'd still have 3 elements in my array, where the ones not explicitly initialized will be default initialized. 如果我提供的太少,我的数组中仍然有3个元素,未明确初始化的元素将默认初始化。
I hope you are convinced by now those are indeed very different types. 我希望你现在确信那些确实是非常不同的类型。 So as template arguments, they shouldn't match.
所以作为模板参数,它们不应该匹配。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.