Does the C++ standard explicitly disallow default arguments in calls through constexpr member function pointers?

旧巷老猫 提交于 2019-12-10 18:42:08

问题


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.


回答1:


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.



来源:https://stackoverflow.com/questions/35980469/does-the-c-standard-explicitly-disallow-default-arguments-in-calls-through-con

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!