C ++标准是否明确禁止通过constexpr成员函数指针调用的默认参数? [英] Does the C++ standard explicitly disallow default arguments in calls through constexpr member function pointers?

查看:149
本文介绍了C ++标准是否明确禁止通过constexpr成员函数指针调用的默认参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑下面的代码:

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

constexpr auto ptr =& foo :: bar;

int main(){
return(foo {}。* ptr)(0);
}



如预期,此代码无法使用最新版本的GCC,Clang,然而,似乎假设的编译器能够传递默认参数通过 constexpr 成员函数指针。如果此编译器在没有警告< / edit> 的情况下成功编译了代码< edit> ,则有效地传递 0,0 foo :: bar ,它仍然符合ISO C ++标准吗?



参考标准(或其工作草案)。

如果标准对此问题没有评论,我将接受作为答案。

解决方案

C ++标准没有明确禁止大多数不合格的结构,包括这一个。



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



为了解决后一个问题,我们应该确定 constexpr 是否具有任何相关性。答案是肯定的不。 constexpr 关键字导致某些表达式,否则不是常量表达式成为这样,并没有其他意义。反过来,常量表达式与严格限定数量的明确定义的上下文中的普通表达式不同,例如数组声明或模板实例化。在这样的上下文中,非常量表达式将使程序变得不成形。因为在所讨论的程序中没有这样的上下文,我们必须得出结论: constexpr 与程序的良好形式无关。



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

 `(int *)nullptr  - (int *)nullptr`

格式正确,而

 `(int *)nullptr  - (double *)nullptr`

尽管两个操作数都是常量表达式,但在编译期间等于 nullptr


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


所以我们必须检查程序sans constexpr 是否正确。令人惊讶的是,这个问题在标准中没有直接的答案,事实上可能根本没有答案。根据C ++的静态类型的性质,调用应该是不成形的,但是我找不到这种效果的直接声明。



标准间接地说明了默认的函数参数是什么? 而不是函数本身的属性:


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


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


Consider the code below:

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

constexpr auto ptr = &foo::bar;

int main() { 
    return (foo{}.*ptr)(0);
}

As expected, this code fails to compile with recent versions of GCC, Clang, and MSVC.

It is, however, plausible that a hypothetical compiler be capable of passing default arguments through aconstexpr member function pointer. If this compiler successfully compiled the code above <edit> without warnings </edit>, effectively passing 0, 0 to foo::bar, would it still conform to the ISO C++ standard?

An acceptable answer will reference the standard (or a working draft thereof). I have not yet found an answer in working draft N4567.

Edit: If the standard has no comment on this issue, I'll accept that as an answer as well.

解决方案

The C++ standard does not explicitly disallow most ill-formed constructs, including this one. It is enough for it to not be explicitly or implicitly allowed to be ill-formed.

A conforming C++ implementation is allowed to accept anything at all, including ill-formed C++ programs. It is, however, require to issue at least one diagnostic if the input is not a well-formed C++ program (except in cases where an explicit "no diagnostic required" clause is present in the standard). So the question of what a conforming compiler is allowed to do rests on the question of whether the program in question is well-formed.

In order to address this latter question, we should establish whether constexpr bears any relevance. The answer to this is a definite "no". The constexpr keyword causes certain expressions that are otherwise not constant-expressions to become such, and has no other meaning. In turn, constant-expressions are different from plain vanilla expressions in a strictly limited number of well-defined contexts, such as array declarations or template instantiations. In such contexts a non-constant expression would render the program ill-formed. Since no such context is present in the program in question, we must conclude that constexpr bears no relevance on well-formedness of the program.

In particular, being a constant-expression does not free an expression from its obligation to be type-correct. As a trivial example,

`(int*)nullptr - (int*)nullptr`

is well-formed, while

`(int*)nullptr - (double*)nullptr`

is type-incorrect and thus ill-formed, despite both operands being constant expressions, known at compile-time to be equal to nullptr.

Disclaimer: C-style casts are for demonstration purpose only, as they read better in short code snippets. Don't use them in production code.

So we have to examine whether the program sans constexpr is well-formed or not. This question, surprisingly, doesn't have a direct answer in the standard, and may in fact have no answer at all. According to the statically-typed nature of C++, the call should be ill-formed, but I could not find a direct statement to this effect. Rather than pondering potential implications of this, I would rather declare this a technical defect of the standard and call it a day.

The standard does indirectly state that default function arguments are properties of function declarations rather than functions themselves:

(8.3.6/4) Declarations in different scopes have completely distinct sets of default arguments

Thus, a function pointer, being an entity that references a function rather than a function declaration, should not have default arguments applied.

这篇关于C ++标准是否明确禁止通过constexpr成员函数指针调用的默认参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆