【发布时间】:2020-01-07 07:18:24
【问题描述】:
在某些情况下,例如使用 always_false 助手如果尝试实例化某个模板,则会导致无条件的 static_assert 失败:
template <class... T> struct always_false : std::false_type {};
template<class T>
struct UsingThisShouldBeAnError {
static_assert(always_false<T>::value, "You should not use this!");
};
这个助手是必要的,因为模板定义必须(至少在理论上)具有至少一组模板参数,可以为其生成有效的特化,以使程序具有良好的格式:
[temp.res]/8:程序格式错误,不需要诊断,如果:
- 无法为模板生成有效的特化 [...] 并且模板未实例化,或者
[...]
(因此,在上面编写 static_assert(false, "You should not use this!"); 格式不正确,编译器总是可以触发静态断言,即使没有实例化模板,这不是本意。)
以下是涉及此模式的问题的快速示例(包括进一步的解释):
将always_false 作为标准库中的工具可能会很有用,这样我们就不必不断地重新编写它。但是,以下问题的答案让我怀疑这是否可能:
Dependent non-type parameter packs: what does the standard say?
这里有一个论点(也关于 [temp.res]/8)std::enable_if_t<T> 始终要么是 void 要么不是类型,并且任何人进一步专门化它都是非法的。因此,依赖std::enable_if 的理论“特化性”来避免 [temp.res]/8 子句的模板实际上会导致程序格式错误,不需要诊断。
回到我的问题:如果标准提供了always_false,它就必须禁止图书馆用户像往常一样对其进行专业化(原因很明显)。但是根据上述推理,这将破坏always_false 的全部观点(即理论上它可以专门用于std::false_type 以外的其他东西) - 就 [temp.res]/8 而言,它与使用相同直接std::false_type。
我的推理错了吗?或者标准库实际上不可能以有意义/有用的方式提供always_false(无需更改核心语言)?
【问题讨论】:
-
标准库可以做在用户代码中非法的事情,所以我会说是的,标准库有可能实现这样的构造,即使它是非法的。不过不要引用我的话。
-
@bolov:问题是用户的使用。类定义很简单,没有问题。但是一旦进入
std,就会对用户施加额外的限制(除非允许,否则没有专业化)。 -
@Jarod42 天哪,C++ 竟然有这么阴暗的角落……
标签: c++ templates template-specialization