作为模板类型参数,为什么 type[N] 不匹配它的专用版本---- template<class T> class S<T[]>
As template type argument, why doesn't type[N] match its specialized version ---- template<class T> class S<T[]>
这是一个演示(从 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';
}
输出(live demo
):
false
true
false
我们可以看到 is_array<A[3]>
被解析为主要专业:template<class T> struct is_array
,而不是 template<class T> struct is_array<T[]>
。
这让我有点困惑。当然,我知道 std::is_array
的完整实现(如 cppreference 中所述)还包含长度的特化:template<class T, std::size_t N> struct is_array<T[N]>
,并且 std::is_array<A[3]>
将按预期解决此特化。但这不能解释最上面的演示,对吧?
搜索后发现this thread, but it is a question about how, not why. But in a comment, @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.
似乎与 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 N T”) are different types. 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
extern int arr[]; // the type of arr is incomplete
int arr[10]; // now the type of arr is complete
[basic.types]/6 没有提供任何其他关于此的有用信息。
我注意到规范示例中的一个错误,这让我想到这可能与专业化无关,而是因为 A[3]
无法匹配 struct is_array<T[]>
。这就是编译器似乎确认的内容:
#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
}
以上是我自己尝试解决的,没有成功。所以我来这里是为了找到一个彻底的答案。
简短的答案在你自己引用的段落中:
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 N T”) are different types. 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
这些是不同的类型。虽然您可能 "fix" 数组的类型 object 在声明的第一点之后,它仍然不会改变它们是不同类型的事实。他们的行为不同。例如:
using AI = int[];
using AC = int[3];
AI a1 = {1, 2, 3, 4};
AC a2 = {1, 2, 3, 4}; // error
对象 a1
可以用初始化器 {1, 2, 3, 4}
初始化。我们看到我别名为 AI
的类型有点像 auto
,可以使用初始值设定项来帮助推导完整类型。
另一方面,a2
会导致错误,因为我提供了太多的初始值设定项。如果我提供的太少,我的数组中仍然有 3 个元素,其中未显式初始化的元素将被默认初始化。
我希望你现在确信这些确实是非常不同的类型。因此作为模板参数,它们不应该匹配。
这是一个演示(从 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';
}
输出(live demo
):
false
true
false
我们可以看到 is_array<A[3]>
被解析为主要专业:template<class T> struct is_array
,而不是 template<class T> struct is_array<T[]>
。
这让我有点困惑。当然,我知道 std::is_array
的完整实现(如 cppreference 中所述)还包含长度的特化:template<class T, std::size_t N> struct is_array<T[N]>
,并且 std::is_array<A[3]>
将按预期解决此特化。但这不能解释最上面的演示,对吧?
搜索后发现this thread, but it is a question about how, not why. But in a comment, @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.
似乎与 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 N T”) are different types. 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
extern int arr[]; // the type of arr is incomplete
int arr[10]; // now the type of arr is complete
[basic.types]/6 没有提供任何其他关于此的有用信息。
我注意到规范示例中的一个错误,这让我想到这可能与专业化无关,而是因为 A[3]
无法匹配 struct is_array<T[]>
。这就是编译器似乎确认的内容:
#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
}
以上是我自己尝试解决的,没有成功。所以我来这里是为了找到一个彻底的答案。
简短的答案在你自己引用的段落中:
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 N T”) are different types. 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
这些是不同的类型。虽然您可能 "fix" 数组的类型 object 在声明的第一点之后,它仍然不会改变它们是不同类型的事实。他们的行为不同。例如:
using AI = int[];
using AC = int[3];
AI a1 = {1, 2, 3, 4};
AC a2 = {1, 2, 3, 4}; // error
对象 a1
可以用初始化器 {1, 2, 3, 4}
初始化。我们看到我别名为 AI
的类型有点像 auto
,可以使用初始值设定项来帮助推导完整类型。
另一方面,a2
会导致错误,因为我提供了太多的初始值设定项。如果我提供的太少,我的数组中仍然有 3 个元素,其中未显式初始化的元素将被默认初始化。
我希望你现在确信这些确实是非常不同的类型。因此作为模板参数,它们不应该匹配。