简体   繁体   English

作为模板类型参数,为什么不键入[N]匹配其专用版本 - 模板 <class T> S级 <T[]>

[英]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
}

demo


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.

相关问题 模板参数中的派生 class 类型无法编译 - Derived class type in template argument doesn't compile SFINAE:编译器不选择专门的模板类 - SFINAE: Compiler doesn't pick the specialized template class 是否可以在模板类中编写一个静态可变参数模板函数,该函数可以接受N个类型为T的参数? - Is it possible to write a static variadic template function, in a template class, that's able to take N parameters of type T? 为什么带有指针子对象的文字 class 类型的 constexpr 表达式不能是非类型模板参数 - why a constexpr expression of literal class type with a pointer subobject can't be a non-type template argument 为什么模板非类型参数不能是类类型 - Why can't template non type parameters be of class type 根据类型模板的类型参数自动执行其大小参数 - Automating a class template's size argument based on its type argument 错误:“模板”模板参数列表中参数1处的类型/值不匹配 <class T> QList类” - error: type/value mismatch at argument 1 in template parameter list for 'template<class T> class QList' 非模板类T的模板成员函数(在T类型上) - Template member function (on type T) of non-template class T 为什么模板类型不能成为C ++中的友元类? - Why can't a template type be a friend class in C++? 为什么我不能将类的类型成员作为模板参数传递? - Why can't I pass a type member of a class as a template parameter?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM