C++标准是否明确禁止通过 constexpr 成员函数指针调用默认参数?
Does the C++ standard explicitly disallow default arguments in calls through constexpr member function pointers?
请考虑以下代码:
struct foo {
int bar(int, int = 0) {
return 0;
}
};
constexpr auto ptr = &foo::bar;
int main() {
return (foo{}.*ptr)(0);
}
正如预期的那样,此代码无法使用最新版本的 GCC、Clang 和 MSVC 进行编译。
但是,假设的编译器能够通过constexpr
成员函数指针传递默认参数是合理的。如果这个编译器成功地编译了上面的代码0, 0
传递给foo::bar
,它是否仍然符合ISO C++标准?
可接受的答案将参考标准(或其工作草案)。我还没有在工作草案N4567中找到答案。
编辑:如果标准对这个问题没有评论,我也会接受它作为答案。
C++ 标准并没有明确禁止大多数格式错误的构造,包括这个。不明确或隐含地允许它格式不正确就足够了。
允许符合C++的实现接受任何内容,包括格式不正确的C++程序。但是,如果输入不是格式正确的C++程序,则需要发出至少一个诊断(除非标准中存在明确的"无需诊断"子句)。因此,允许符合要求的编译器执行哪些操作的问题取决于所讨论的程序是否格式正确的问题。
为了解决后一个问题,我们应该确定constexpr
是否具有任何相关性。答案是肯定的"不"。constexpr
关键字会导致某些原本不是常量表达式的表达式变成常量表达式,并且没有其他含义。反过来,常量表达式与严格限制数量的明确定义的上下文(如数组声明或模板实例化)中的普通香草表达式不同。在这种情况下,非常量表达式会使程序格式不正确。由于所讨论的程序中不存在这样的上下文,因此我们必须得出结论,constexpr
与程序的良好形式无关。
特别是,作为常量表达式并不能使表达式免于其类型正确的义务。举个微不足道的例子,
`(int*)nullptr - (int*)nullptr`
格式良好,而
`(int*)nullptr - (double*)nullptr`
类型不正确,因此格式不正确,尽管两个操作数都是常量表达式,在编译时已知等于 nullptr
。
免责声明:C 样式转换仅用于演示目的,因为它们在短代码片段中读起来更好。不要在生产代码中使用它们。
因此,我们必须检查程序是否constexpr
格式正确。令人惊讶的是,这个问题在标准中没有直接答案,实际上可能根本没有答案。根据C++的静态类型性质,调用应该是格式错误的,但我找不到这种效果的直接语句。与其考虑这样做的潜在影响,我宁愿宣布这是标准的技术缺陷,并称之为一天。
该标准确实间接声明默认函数参数是函数声明的属性,而不是函数本身:
因此,函数(8.3.6/4)不同作用域的声明具有完全不同的默认参数集
指针作为引用函数而不是函数声明的实体,不应应用默认参数。
- 如何正确编写指针函数声明?
- C++常规指针函数或模板
- 如何重新定义 C++ 指针函数?
- C++ 指向其他类函数的指针函数
- 指针到指针函数参数
- 将指向成员的指针函数传递到模板中
- C++ 在 none 常量指针函数中返回一个常量指针
- 如何使用指针函数编写/读取数组
- 是C 中的函数指针函数对象
- 如何从另一个类调用指向成员的指针函数
- 如何声明采用指向成员的指针函数的函数
- 如何构造一个以可变参数指针函数作为成员的类?
- c 通过值或指针函数语法
- 将typedef方法作为指针函数传递
- 从 Main 中的双指针函数打印出指针数组
- strcpy 对指针函数的引用
- 这是否仍然声明一种指针函数的别名?
- 将指向成员的指针函数与 std::shared_ptr 结合使用
- 'Incomplete type' 为标准::函数声明指向成员的指针函数模板参数时出错
- 从注入进程的 DLL 调用函数并更改指针函数的地址