Understanding 'most vexing parse' - why allow ambiguous syntax?

六眼飞鱼酱① 提交于 2019-12-18 07:03:17

问题


While trying to understand the "Most vexing parse" problem in C/C++, this question immediately springs to mind - why have a syntax that causes this problem to begin with?

For example,

class Timer
{
public:
    Timer();
};

class TimeKeeper
{
public:
    TimeKeeper(const Timer& t);

    int get_time()
    {
        return 1;
    }
};

int main()
{
    TimeKeeper time_keeper(Timer());
    // the above is eq to this: TimeKeeper time_keeper(Timer (*)());
}

So why not simply disallow TimeKeeper time_keeper(Timer()) to be a function declaration that takes an unnamed function ptr returning type Timer? Is TimeKeeper time_keeper(Timer (*)()) inferior as a function declarator?

Is it not due to this syntax that we even get this ambiguity or am I missing something?

EDIT: Personally, I've never used TimeKeeper time_keeper(Timer()) as a function declaration. I've always used the Timer (*)() to specify a function pointer as I find it clearer.


回答1:


So why not simply disallow TimeKeeper time_keeper(Timer()) to be a function declaration that takes an unnamed function ptr returning type Timer?

Suppose for a while that this function declaration is diallowed, because it uses unnamed parameter. If that is so, then the following declarations will be disallowed as well:

int max(int,int);  //error (in hypothetical C++)
int min(int,int);  //error (in hypothetical C++)

And then the programmers will be forced to write the parameter name, in the declarations as well:

int max(int a,int b);  //ok 
int min(int a,int b);  //ok 

But then someone else would stand up and ask : "Why am I forced to write the parameter name(s) in the declarations when it doesn't use it? Why is it not optional?"

I think this guy is rational and what he asked has point. It is indeed irrational to force programmers to name the parameter in the declarations.

--

Reading your comment, it seems that you think the following declarations are exactly same:

int max(Timer());
int max(Timer(*)());

No. They're not exactly same from the syntax point of view, though they are exactly same from the behavior point of view.

The subtle difference is that in the former, the parameter type is a function which takes nothing, and returns Timer, while in the later, the parameter type is a pointer to a function which takes nothing, and returns Timer. Do you see the difference?

But then the question is, why are they same behavior-wise? Well the answer is, in the former declaration, the parameter type is adjusted and then becomes a pointer type, and so it behaves the same as the second declaration.

The C++03 Standard says in §13.1/3,

Parameter declarations that differ only in that one is a function type and the other is a pointer to the same function type are equivalent. That is, the function type is adjusted to become a pointer to function type (8.3.5).

I hope it is same in C++11 also.

--

Your doubt (taken from the comment):

Still not any closer to understanding why we need the 2 syntax?

Because they are two different types. Function type, and pointer to function type. Only as parameter type, they behaves same. Otherwise, they're different. See my answer here to see where they behave differently:

  • Reference to Function syntax - with and without &

And since they behave differently in other situations, we have them, we need them. The Standard doesn't (and should not) disallow one syntax, just because as parameter type they behave same.




回答2:


Just a note that... you have been heard :)

C++11 specifically addressed this issue with the introduction of the uniform initialization syntax. Now you can write TimeKeeper time_keeper{Timer{}}; and there is no parse ambiguity.



来源:https://stackoverflow.com/questions/11535388/understanding-most-vexing-parse-why-allow-ambiguous-syntax

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