请考虑以下代码:
struct foo {
int bar(int, int = 0) {
return 0;
}
};
constexpr auto ptr = &foo::bar;
int main() {
return (foo{}.*ptr)(0);
}
正如所料,此代码无法使用最新版本的GCC,Clang和MSVC进行编译。
然而,假设编译器能够通过constexpr
成员函数指针传递默认参数是合理的。如果此编译器成功编译了< edit> 上面的代码而没有警告< / edit> ,有效地将0, 0
传递给foo::bar
,那么仍然符合ISO C ++标准?
可接受的答案将参考标准(或其工作草案)。我还没有在N4567的工作草案中找到答案。
修改:如果标准没有对此问题发表评论,我也会接受这个问题。
答案 0 :(得分:6)
C ++标准没有明确禁止大多数不正确的构造,包括这个构造。它不足以明确或隐含地允许其形成不良。
允许符合标准的C ++实现接受任何内容,包括格式错误的C ++程序。但是,如果输入不是格式良好的C ++程序,则需要发出至少一个诊断(除非标准中存在明确的“无需诊断”条款)。因此,允许合规编译器做什么的问题取决于所讨论的程序是否格式正确。
为了解决后一个问题,我们应该确定constexpr
是否具有相关性。答案是肯定的“不”。 constexpr
关键字导致某些不是常量表达式的表达式变为这样,并且没有其他含义。反过来,常量表达式与严格限定数量的明确定义的上下文中的普通表达式不同,例如数组声明或模板实例化。在这种情况下,非常数表达式会导致程序格式不正确。由于该计划中没有这样的背景,我们必须得出结论,constexpr
与计划的良好形成无关。
特别是,作为一个常量表达式并不能使表达式免于其类型正确的义务。作为一个简单的例子,
`(int*)nullptr - (int*)nullptr`
格式正确,而
`(int*)nullptr - (double*)nullptr`
是类型不正确的,因此格式不正确,尽管两个操作数都是常量表达式,在编译时已知等于nullptr
。
免责声明:C风格的演员表仅用于演示目的,因为它们在短代码片段中读得更好。不要在生产代码中使用它们。
所以我们必须检查一下constexpr
程序是否格式正确。令人惊讶的是,这个问题在标准中没有直接的答案,实际上可能根本没有答案。根据C ++的静态类型性质,调用应该是格式错误的,但我找不到直接声明这种效果。我宁愿宣布这是标准的技术缺陷,而是将其称为一天。
标准确实间接声明默认函数参数是函数声明的属性而不是函数本身:
(8.3.6 / 4)不同范围内的声明具有完全不同的默认参数集
因此,作为引用函数而不是函数声明的实体的函数指针不应该应用默认参数。