C++ 使用“void”专门化模板的规则是什么?

C++ 使用“void”专门化模板的规则是什么?,c++,templates,C++,Templates,这是我刚才在野外写的一个精简的插图。我真的没想到它会起作用,但它确实起作用了 #include <array> template <typename T> using Foo = std::array<T,123>; const int FOO_SIZE = std::tuple_size<Foo<void>>::value; #包括 使用Foo=std::array的模板; const int FOO_SIZE=std::tup

这是我刚才在野外写的一个精简的插图。我真的没想到它会起作用,但它确实起作用了

#include <array>

template <typename T> using Foo = std::array<T,123>;

const int FOO_SIZE = std::tuple_size<Foo<void>>::value;
#包括
使用Foo=std::array的模板;
const int FOO_SIZE=std::tuple_SIZE::value;
我不确定使用
void
专门化
Foo
是否可以编译,但至少在本例中是这样

我不相信这个解决方案是可移植的,或者说这只是一个侥幸,因为
std::array
的实现恰好与空洞数组的概念兼容,这听起来像是胡说八道


什么时候可以,什么时候不可以,使用
void
专门化模板?

如果不复制一半的标准(:D),我无法找到真正令人信服的特定标准措辞,但我相信这是定义明确的

array
构造函数要求
T
是可移动构造的或可移动分配的,并且您将无法实例化
std::array

但这很好,因为
std::tuple\u size
不需要这样做,也没有指定需要这样做,而且这两件事都不会使任何其他特定需求成为代码问题


但是,这似乎不是有用的代码,并且没有关于何时可以将
void
用作模板参数的一般规则。您必须在使用它的特定上下文中查看所使用的特定对象的要求。

从表面上看,这种编译似乎令人惊讶,因为类型为void的数组被(N4659工作草案中的11.3.4:2)明确排除在外:

数组可以从基本类型之一构造(除了 void),从指针,从指向成员的指针,从类,从 枚举类型,或来自其他数组

std::array
通常是直接以数组的形式实现的,因此任何使用它的尝试都会失败


<>但是C++在模板实例化中有错误的大量规则,这些规则在编译实际使用时不是直接需要的。在这种情况下,我相信代码是有效的并且是可移植的,因为
std::tuple\u size::value
的计算实际上并没有实例化
Foo
,但是我认为这样的用法是不正当的,你应该避免使用,因为除了这样的例外情况之外,
Foo
没有任何有效性。

你可以重新排序:
constepr::std::size\u t const Foo\u size{123};使用Foo=std::array的模板
tuple\u size
不会实例化其
tuple
/
数组
。实例化
Foo
会产生硬错误。是否指定
tuple\u size
不会实例化
数组
,或者这只是实现的偶然情况?@spraff只是没有指定它会,并且它的任何行为都不要求它:)这不是实现的偶然情况,尽管您可能会争辩说这是规范的偶然事件