C++标准是否通过constexpr成员函数指针明确禁止调用中的默认参数?

Bar*_*air 3 c++ language-lawyer constexpr c++11

请考虑以下代码:

struct foo {
    int bar(int, int = 0) {
        return 0;
    }
};

constexpr auto ptr = &foo::bar;

int main() { 
    return (foo{}.*ptr)(0);
}
Run Code Online (Sandbox Code Playgroud)

正如所料,此代码无法使用最新版本的GCC,Clang和MSVC进行编译.

但是,假设的编译器能够通过constexpr成员函数指针传递默认参数是合理的.如果这个编译器成功编译了<edit>上面的代码而没有警告</ edit>,有效地传递0, 0给foo::bar它,它是否仍然符合ISO C++标准?

可接受的答案将参考标准(或其工作草案).我还没有在N4567的工作草案中找到答案.

编辑:如果标准没有对此问题发表评论,我也会接受这个问题.

n. *_* m. 6

C++标准没有明确禁止大多数不正确的构造,包括这个构造.它不足以明确或隐含地允许其形成错误.

一致的C++实现允许接受任何东西,包括不正确的C++程序.但是,如果输入不是格式良好的C++程序,则需要发出至少一个诊断(除非标准中存在明确的"无需诊断"条款).因此,允许符合标准的编译器的问题取决于所讨论的程序是否格式正确.

为了解决后一个问题,我们应该确定是否constexpr有任何相关性.答案是肯定的"不".该constexpr关键字导致某些表达式不是常量表达式,而是没有其他含义.反过来,常量表达式与严格限定数量的明确定义的上下文中的普通表达式不同,例如数组声明或模板实例化.在这种情况下,非常数表达式会导致程序格式不正确.由于该计划中没有这样的背景,我们必须得出结论,这constexpr与计划的良好形成无关.

特别是,作为一个常量表达式并不能使表达式免于其类型正确的义务.作为一个简单的例子,

`(int*)nullptr - (int*)nullptr`
Run Code Online (Sandbox Code Playgroud)

形象良好,而

`(int*)nullptr - (double*)nullptr`
Run Code Online (Sandbox Code Playgroud)

尽管两个操作数都是常量表达式,但在编译时已知等于,因此类型不正确并因此形成错误nullptr.

免责声明:C风格的演员表仅用于演示目的,因为它们在短代码片段中读得更好.不要在生产代码中使用它们.

因此,我们必须检查程序sans constexpr是否形式良好.令人惊讶的是,这个问题在标准中没有直接的答案,实际上可能根本没有答案.根据C++的静态类型性质,调用应该是格式错误的,但我找不到直接声明这种效果.我宁愿宣布这是标准的技术缺陷而是将其称为一天,而不是考虑这种潜在影响.

该标准间接声明默认函数参数是函数声明的属性而不是函数本身:

(8.3.6/4)不同范围内的声明具有完全不同的默认参数集

因此,作为引用函数而不是函数声明的实体的函数指针不应该应用默认参数.