C++ parsing problem
|
|
Thread rating:  |
Alexey Proskuryakov - 13 Jan 2004 14:30 GMT Hi!
I'm converting a project to CW 9, and have run into a problem with a piece of code that was fine for CW 8.
Here is a (minimized) code snippet that gives an error. As both CW 9 and gcc dislike it in the same way, I suppose that it's my bug. So, why isn't this proper C++, and is there a good workaround?
-------------------------------
#include <vector> #include <utility>
struct C { int f( const std::vector< std::pair<int, int> > & inExtraHeaders = std::vector< std::pair<int, int> >() );
};
-------------------------------
Error : ')' expected SimpleAlert.cp line 8 std::vector< std::pair<int, int> >()
Error : ';' expected SimpleAlert.cp line 8 std::vector< std::pair<int, int> >()
Error : illegal default argument(s) SimpleAlert.cp line 8 std::vector< std::pair<int, int> >()
- WBR, Alexey Proskuryakov
MW Ron - 13 Jan 2004 15:52 GMT >Hi! > [quoted text clipped - 29 lines] >Error : illegal default argument(s) >SimpleAlert.cp line 8 std::vector< std::pair<int, int> >() Hi, This is documented in the 3.2 release notes:
---
* Deferred parsing of default arguments in member functions is now enabled by default (#pragma defer_defarg_parsing on). Note that some default expressions with template argument list will now have to be parenthesized:
template<typename T,typename U> struct X { T t; U u; }; struct Y { void f(X<int,int> = X<int,int>()); // error, not accepted with defer_defarg_parsing on };
Fix:
template<typename T,typename U> struct X { T t; U u; }; struct Y { void f(X<int,int> = (X<int,int>()) ); // OK if default argument is parenthesized };
See also core issue 325. (copied below)
So we implemented the suggested solution for core issue 325:
> Suggested resolution: > [quoted text clipped - 4 lines] > default argument expressions shall not require evaluation of a default > argument of a function declared later in the class. And you have to use:
#include <vector> #include <utility>
struct C { int f( const std::vector< std::pair<int, int> > & inExtraHeaders = ( std::vector< std::pair<int, int> >() ) );
};
Ron
 Signature Metrowerks, maker of CodeWarrior - "Software Starts Here" Ron Liechty - MWRon@metrowerks.com - <http://www.metrowerks.com>
Alexey Proskuryakov - 14 Jan 2004 08:53 GMT Hi!
Thank you for the in-depth clarification and workaround. The workaround suggested by Dave helps as well.
However, I'm a bit confused about issue 325. Is it that I misinterpret the suggested solution, or CW 9.1 actually doesn't implement it? The comma in both my example and the one from release notes is very well bracketed (with angle brackets), so it shouldn't mark an end of default argument expression.
Of course, this issue is still in "open" state, so no means of handling it can be formally correct, I guess :)
On 13.01.2004 18:52, in article mwron-3F612A.10523813012004@enews.newsguy.com, "MW Ron" <mwron@metrowerks.com> wrote:
> Hi, This is documented in the 3.2 release notes: > [quoted text clipped - 32 lines] >> default argument expressions shall not require evaluation of a default >> argument of a function declared later in the class. - WBR, Alexey Proskuryakov
MW Ron - 14 Jan 2004 15:21 GMT > Thank you for the in-depth clarification and workaround. The workaround >suggested by Dave helps as well. [quoted text clipped - 3 lines] >both my example and the one from release notes is very well bracketed (with >angle brackets), so it shouldn't mark an end of default argument expression. Deferred parsing of default arguments in member functions is now enabled by default, in CW 8.3 you'd have to specifically enable it.
Issue 325 is an issue in the Standards (default arguments) that is going to be changed with this suggested resolution which we have adapted prior to it being formally approved.
Suggested resolution: Append the following text to 8.3.6 dcl.fct.default paragraph 8. The default argument expression of a member function declared in the class definition consists of the sequence of tokens up until the next non-parenthesized, non-bracketed comma or close parenthesis. Furthermore such default argument expressions shall not require evaluation of a default argument of a function declared later in the class.
Does that explain it better.
Ron
 Signature Metrowerks, maker of CodeWarrior - "Software Starts Here" Ron Liechty - MWRon@metrowerks.com - <http://www.metrowerks.com>
Alexey Proskuryakov - 15 Jan 2004 08:44 GMT On 14.01.2004 18:21, in article mwron-0D1D79.10215614012004@news.newsguy.com, "MW Ron" <mwron@metrowerks.com> wrote:
> Deferred parsing of default arguments in member functions is now > enabled by default, in CW 8.3 you'd have to specifically enable it. [quoted text clipped - 14 lines] > > Does that explain it better. Please, consider the example from the 9.0 release notes:
// ---------------------- template<typename T,typename U> struct X { T t; U u; }; struct Y { void f(X<int,int> = X<int,int>()); // error, not accepted with defer_defarg_parsing on }; // ----------------------
Here, the default argument expression starts after the '=' sign and should continue "up until the next non-parenthesized, non-bracketed comma or close parenthesis". The next comma (between ints) is bracketed, so the default argument continues until the next closing parenthesis, and should be "X<int,int>()".
So, although the standard doesn't require that this declaration is parsed without error, the suggested solution makes it valid.
Please also note that Comeau online compiler also thinks that this code is OK. I have previously reported that gcc behaves like CW 9, but have since found that they have a bug filed against this, and just don't want to change anything until the issue is formally closed by the comittee.
This is what makes me believe that CW 9 doesn't implement the suggested solution to issue 325 (but breaks compatibility with CW 8 in default mode for no apparent reason).
- WBR, Alexey Proskuryakov
MW Ron - 15 Jan 2004 14:49 GMT >On 14.01.2004 18:21, in article >mwron-0D1D79.10215614012004@news.newsguy.com, "MW Ron" [quoted text clipped - 42 lines] >found that they have a bug filed against this, and just don't want to change >anything until the issue is formally closed by the comittee. Right as I understand we are ahead of the loop not behind the loop on this one. I may not fully understand this though.
> This is what makes me believe that CW 9 doesn't implement the suggested >solution to issue 325 (but breaks compatibility with CW 8 in default mode >for no apparent reason). You could be right trying to read the standards often gives me a headache let alone the committee actions. Andreas is the one that wrote up the reply and he believes he is doing the right thing. Send me an e-mail and I'll forward it on to him, he is open and will listen and correct any misunderstandings he or explain why he went this way. If we are wrong we will correct it.
Ron
 Signature Metrowerks, maker of CodeWarrior - "Software Starts Here" Ron Liechty - MWRon@metrowerks.com - <http://www.metrowerks.com>
MW Ron - 15 Jan 2004 17:48 GMT > Please, consider the example from the 9.0 release notes: > [quoted text clipped - 23 lines] >solution to issue 325 (but breaks compatibility with CW 8 in default mode >for no apparent reason). First off, if you want the compatibility with CW 8.3 you can just use a pragma
#pragma defer_defarg_parsing off
your original version compiles then.
Andreas's reply to your comments was...
The comma between int,int is not [bracketed] and not (parenthesized), so I think my solution is correct.
The core defect and resolution was actually reported by one of the GCC authors.
There are good reasons for this change, the C++ grammar is highly ambiguous and some (other) examples cannot be properly parsed without this change.
Ron
 Signature Metrowerks, maker of CodeWarrior - "Software Starts Here" Ron Liechty - MWRon@metrowerks.com - <http://www.metrowerks.com>
David Phillip Oster - 13 Jan 2004 15:56 GMT > ------------------------------- > [quoted text clipped - 11 lines] > > ------------------------------- If you replace the vector type by V, you get:
typedef std::vector< std::pair<int, int> > V;
struct C { int f(const V& inExtraHeaders = V()); };
Clearly, after the equal sign should be a value, not an extern function declaration (which is what V() is.)
struct C { private: static const V v; public: int f(const V& inExtraHeaders = v); };
Dave Baum - 13 Jan 2004 16:37 GMT > If you replace the vector type by V, you get: > [quoted text clipped - 6 lines] > Clearly, after the equal sign should be a value, not an extern > function declaration (which is what V() is.) I believe that in this context, V() is a call to the default constructor for type V, and is valid C++. It should result in a new local instance of V being constructed (and destructed after f() exits).
Dave
David Phillip Oster - 13 Jan 2004 18:06 GMT > > If you replace the vector type by V, you get: > > [quoted text clipped - 10 lines] > for type V, and is valid C++. It should result in a new local instance > of V being constructed (and destructed after f() exits). You are right. I'd gotten confused with:
int f(){ V v(); // declare "v" to be an extern function, returning a V. V v1; // declares a variable of type V, calling no-arg constructor. }
Dave Baum - 13 Jan 2004 16:17 GMT > Hi! > [quoted text clipped - 4 lines] > gcc dislike it in the same way, I suppose that it's my bug. So, why isn't > this proper C++, and is there a good workaround? I'm not sure why it isn't proper C++. Interestingly enough, if you make a typedef for pair<int,int> then gcc seems to like it better. Would this be an acceptable workaround?
------------------------------- #include <vector> #include <utility>
typedef std::pair<int,int> P;
struct C {
int f( const std::vector< P > & inExtraHeaders = std::vector< P >() );
};
------
I don't have CW9 so I couldn't verify with that compiler.
Dave
> ------------------------------- > [quoted text clipped - 22 lines] > > - WBR, Alexey Proskuryakov
|
|
|