C++ goto (rather than continue) syntactic oddity - c++

I have the following code:
do
{
doStuffP1();
if (test)
{ goto skip_increment;
}
dostuffP2();
skip_increment:
// 1; // Only works if I remove the comment at line start.
} while (loop);
Which doesn't compile (VC++ 2010) with this error:
file_system_helpers.cpp(109) : error C2143: syntax error : missing ';' before '}'
If I change it to:
skip_increment:
1;
It compiles (and works).
Is this really a limitation of C++ syntax?

I assume the "1;" was supposed to be missing from your first code snippet?
Look at this grammar here: http://www.lysator.liu.se/c/ANSI-C-grammar-y.html
This defines labels only as a "labeled-statement". That is, a block body can contain label: <statement> anywhere in its sequence of contents, but the statement after the label is not optional. So this would make skip_increment: } invalid.
(And, OK, you're using C++ and not C; but I doubt if making allowances for extra uses of goto was something anyone cared much about while defining the C++ language.)

Related

Strange character added while compilation, leads to an error

When compiling a project with Visual Studio Express 2013, I get this error
....\WDL\IPlug\IPlugVST3.cpp(199): error C2065: 'Lp' : undeclared identifier [D:\wdl-ol\IPlugExamples\MyFirstPlugin\MyFirstPlugin-vst3.vcxproj]
The strange thing is that the file IPlugVST3.cpp doesn't contain Lp but only p:
switch (p->Type())
{
case IParam::kTypeDouble:
case IParam::kTypeInt:
{
Parameter* param = new RangeParameter( STR16(p->GetNameForHost()), // <---- this line
i,
STR16(p->GetLabelForHost()),
p->GetMin(),
p->GetMax(),
p->GetDefault(),
0, // continuous
flags,
unitID);
param->setPrecision (p->GetPrecision());
parameters.addParameter(param);
Why does the C++ compiler understands it a Lp instead of p ?
Note: I checked if there are no hidden unicode characters (does this exist?) but no...
STR16 is most likely a macro which expects a string literal as an argument, e.g.
#define STR16(s) L##s
or something similar. It you pass a variable instead of a string literal then you will get something like the problem you are observing.

Program without semicolon compiles fine in C not in C++ why?

I am using Orwell Dev C++ IDE. Recently I tested following simple program in which I forgot to put semicolon (;) but still it compiles fine in C but not in C++. Why? What is the reason?
// C program compiles & runs fine, even ; missing at end of struct
#include <stdio.h>
struct test
{ int a,b}; // missing semicolon
int main()
{
struct test d={3,6};
printf("%d",d.a);
return 0;
}
[Warning] no semicolon at end of struct or union [enabled by default]
// Following is compilation error in C++
#include <stdio.h>
struct test
{ int a,b}; // missing semicolon
int main()
{
struct test d={3,6};
printf("%d",d.a);
return 0;
}
[Error] expected ';' at end of member declaration
I also tried same C program in codeblocks 13.12 IDE but it shows following error message
error: no semicolon at end of struct or union.
Why different error messages given by different implementations?
The semicolon is required by both languages. Specifically, C specifies the declaration of one or more structure members as
struct-declaration:
specifier-qualifier-list struct-declarator-list ;
and C++ specifies the declaration of one or more class member variables as
member-declaration:
attribute-specifier-seq<opt> decl-specifier-seq<opt> member-declarator-list<opt> ;
both of which require a semicolon at the end.
You'll have to ask the compiler writers why their C++ compiler is more strict than their C compiler. Note that the language specifications only require a "diagnostic" if a program is ill-formed, so it's legitimate either to issue a warning and continue compiling as if the semicolon were present, or to issue an error and stop.
It looks like your IDE is using GCC as its compiler; in which case you could use -Werror to convert warnings into errors, if you'd prefer stricter diagnostics.

error C2143: syntax error : missing ',' before ':'

I'm trying to build am opensource game but keep getting this error when trying to build. I have been searching for the last half hour with nothing working here's the code the errors pointing to
void duel::restore_assumes() {
for(auto pcard : assumes)
pcard->assume_type = 0;
assumes.clear();
}
and the error is
Error 1 error C2143: syntax error : missing ',' before
':' c:\users\user\desktop\project source\ocgcore\duel.cpp 108 1 ocgcore
(Visual Studio 2010)
MS VC++ 2010 does not support the range based for statement that was introduced in the C++ 2011. However it has its own language extension: for each.
Try to change this code
void duel::restore_assumes() {
for(auto pcard : assumes)
pcard->assume_type = 0;
assumes.clear();
}
to
void duel::restore_assumes() {
for each (auto pcard in assumes)
pcard->assume_type = 0;
assumes.clear();
}
Otherwise you can use an ordinary loop with iterators of object assumes or some standard algorithm as for example std::for_each
As shown in this table : C++11 Compiler Support
Range-based for Loops aren't available with MSVC2010, but with MSVC2012 (which is version 11).
So if you use the 2010 compiler, this code won't compile.
The error message makes it pretty obvious: the compiler is not expecting a : in the for statement.

Unusual Error: expected unqualified-id before ')' token

I am trying to take a list data type I created and make it a template. In doing so I've run into the following obscure problem. I can post all of the code if needed, but this is really the function that is causing the problem.
Note: This code was compiling just fine until I got to this method. I was compiling after writing every few lines as a sanity check, and everything was fine, but then I get to this point and it blows up. If I take the try/catch block out of this method it compiles just fine, so I'm pretty sure the problem is isolated there, not a missing semicolon in a header/etc. as reported from other answers -- though I did of course triple-check to be sure! :)
Here's the code that is causing the problem:
template<class T>
bool UnsortedListType<T>::IsFull()
{
try { return false; }
catch(std::bad_alloc exception) { return true; } // line 35
}
Like I said, I simplified it as much as possible while still triggering the error. Here is the error:
UnsortedListType.cpp||In member function 'bool UnsortedListType<T>::IsFull()':
UnsortedListType.cpp|35|error: expected type-specifier
UnsortedListType.cpp|35|error: expected unqualified-id before 'exception'
UnsortedListType.cpp|35|error: expected ')' before 'exception'
UnsortedListType.cpp|35|error: expected '{' before 'exception'
UnsortedListType.cpp|35|error: 'exception' was not declared in this scope
UnsortedListType.cpp|35|error: expected ';' before ')' token
Everything I can find on this error says the problem is either an extra semicolon or a missing semicolon, either in the header or this file. I can't find an instance of either. And if I remove the try/catch block, it compiles fine.
Plus, if I catch an int, it compiles just fine:
template<class T>
bool UnsortedListType<T>::IsFull()
{
try { return false; }
catch(int exception) { return true; }
}
I can also catch(int) and it will compile just fine, but if I try to catch(std::bad_alloc) (i.e. with no "exception" variable name) it throws the same error listed above. Even if I try simply catch(std::exception) it fails to compile.
So now I'm stumped. I'm not an expert at C++ by any stretch, this is for a class, and I'm not sure how to get past this error.
Incidentally, here's the code from the non-generic version, which also compiles just fine, and is verbatim from the textbook I'm using (Dale, if anyone wonders):
bool UnsortedListType::IsFull() const
{
NodeType* location;
try
{
location = new NodeType;
delete location;
return false;
}
catch (std::bad_alloc exception)
{
return true;
}
}
I am using CodeBlocks 12.11 IDE on Windows 7 with the built-in GNU compiler.
Any help appreciated, and I'll be happy to post more code if requested, I just didn't want to fill the page up.
Many thanks in advance.
PS I should state, yes I am doing homework, but the homework doesn't call for me to make a template, I am choosing to go that route myself. Not sure if it has any relevance, but this is the first time I've used C++ templates, so just tossing that out there.
std::bad_alloc is defined in the header <new>, so you need to include that.
Also, it's better to catch exceptions by reference. Catching by value causes a copy, perhaps sliced, of the exception object to be made. Personally I make non-const reference a habit, allowing exception state to be added during handling, but most basic exception types are stateless so there's no practical difference between const & and non-const &.

Strange behaviour with templates and #defines

I have the following definitions:
template<typename T1, typename T2>
class Test2
{
public:
static int hello() { return 0; }
};
template<typename T>
class Test1
{
public:
static int hello() { return 0; }
};
#define VERIFY_R(call) { if (call == 0) printf("yea");}
With these, I try to compile the following:
VERIFY_R( Test1<int>::hello() );
this compiles fine
VERIFY_R( (Test2<int,int>::hello()) );
this also compiles fine, notice the parentheses around the call.
VERIFY_R( Test2<int,int>::hello() );
This, without the parentheses produces a warning and several syntax errors:
warning C4002: too many actual parameters for macro 'VERIFY_R'
error C2143: syntax error : missing ',' before ')'
error C2059: syntax error : ')'
error C2143: syntax error : missing ';' before '}'
error C2143: syntax error : missing ';' before '}'
error C2143: syntax error : missing ';' before '}'
fatal error C1004: unexpected end-of-file found
What's going on here?
This happens with VS2008 SP1.
The comma inside a macro can be ambiguous: an extra set of parentheses (your second example) is one way of disambiguating. Consider a macro
#define VERIFY(A, B) { if ( (A) && (B) ) printf("hi"); }
then you could write VERIFY( foo<bar, x> y ).
Another way of disambiguating is with
typedef Test1<int,int> TestII;
VERIFY_R( TestII::hello() );
The preprocessor is a dumb text replacement tool that knows nothing about C++. It interprets
VERIFY_R( Test1<int,int>::hello() );
as
VERIFY_R( (Test1<int), (int>::hello()) );
which calls VERIFY_R with too many parameters. As you noted, additional parentheses fix this:
VERIFY_R( (Test1<int,int>::hello()) );
The question remains, however, why you need the preprocessor anyway. The macro you used in your question could just as well be an inline function. If you real code doesn't do anything requiring the preprocessor, try to get rid of macros. They just cause pain.
The comma in <int, int> is treated as an argument separator for the macro, rather than for the template. The compiler therefore thinks you're calling VERIFY_R with two arguments (Test1<int and int>::hello()), when it requires only one. You need to use variadic macros to expand everything supplied to the macro:
#define VERIFY_R(...) { if ((__VA_ARGS__) == 0) printf("yea");}
It is generally a good idea to wrap macro arguments in parentheses, as well, to prevent other kinds of weird substitution errors.
The preprocessor doesn't know that < and > are supposed to be brackets, so it interprets the expression as two macro arguments, Test1<int and int>::hello(), separated by the ,. As you say, it can be fixed by surrounding the entire expression with parentheses, which the preprocessor does recognise as brackets.
I'm not sure if this is an error in your reporting here or the actual problem, but your last VERIFY_R is still referencing Test1, rather than Test2.