P0292R1 constexpr如果已包含在内,正在进行 C++ 17.它似乎很有用(并且可以取代SFINAE的使用),但关于static_assert形成不良的评论,假分支中不需要诊断会让我害怕:
Disarming static_assert declarations in the non-taken branch of a
constexpr if is not proposed.
void f() {
if constexpr (false)
static_assert(false); // ill-formed
}
template<class T>
void g() {
if constexpr (false)
static_assert(false); // ill-formed; no
// diagnostic required for template definition
}
Run Code Online (Sandbox Code Playgroud)
我认为它是完全禁止static_assert在constexpr内部使用if(至少是假/非分支,但实际上这意味着它不是一个安全或有用的事情).
这是如何从标准文本中产生的?我发现static_assert在提案中没有提到措辞,并且C++ 14 constexpr函数允许static_assert(cppreference的详细信息:constexpr).
是否隐藏在这个新句子中(6.4.1之后)?:
当constexpr if语句出现在模板化实体中时,在封闭模板或通用lambda的实例化期间,不会实例化丢弃的语句.
从那以后,我认为它也是禁止的,不需要诊断,调用调用图中某个地方可能调用的其他constexpr(模板)函数static_assert.
底线:
如果我的理解是正确的,那么对于constexpr …
在某些情况下,如果尝试实例化某些模板,则使用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!");
};
Run Code Online (Sandbox Code Playgroud)
该帮助程序是必需的,因为模板定义必须(至少在理论上)具有至少一组模板参数,可以为其生成有效的专业化名称,以便程序格式正确:
[temp.res] / 8:如果满足以下条件,则该程序格式错误,无需进行诊断:
- 无法为模板生成有效的专业化,并且模板没有实例化,或者
[...]
(static_assert(false, "You should not use this!");因此,上面的书写格式不正确,即使没有实例化模板,编译器也总是可以触发静态断言,这不是故意的。)
这是涉及此模式的问题的快速样本(包括进一步的解释):
always_false作为标准库中的工具可能会很有用,因此我们不必不断地编写它。但是,以下问题的答案使我怀疑这是否可能:
在那里(std::enable_if_t<T>总是关于[temp.res] / 8)产生一个论点,该论点始终是void或不是一种类型,任何人对其进行进一步专门化都是非法的。因此,依赖于理论上的“ std::enable_if特殊性”的模板可避免[temp.res] / 8子句,实际上会使程序格式错误,不需要诊断。
回到我的问题:如果提供了该标准always_false,它将不得不禁止图书馆用户照常对其进行专业化(出于明显的原因)。但是,根据上述推理,这将使always_false(在理论上可以专门用于除以外的东西std::false_type)整个观点破灭-关于[temp.res] / 8,它将与std::false_type直接使用相同。
我在这个推理上错了吗?还是标准库实际上不可能以always_false有意义/有用的方式提供(无需更改核心语言)?