What's actually going on in this AnonymousClass(variable) declaration? - c++

Trying to compile:
class AnonymousClass
{
public:
AnonymousClass(int x)
{
}
};
int main()
{
int x;
AnonymousClass(x);
return 0;
}
generates errors from MSVC:
foo.cpp(13) : error C2371: 'x' : redefinition; different basic types
foo.cpp(12) : see declaration of 'x'
foo.cpp(13) : error C2512: 'AnonymousClass' : no appropriate default constructor available
g++'s error messages are similar:
foo.cpp: In function ‘int main()’:
foo.cpp:13: error: conflicting declaration ‘AnonymousClass x’
foo.cpp:12: error: ‘x’ has a previous declaration as ‘int x’
foo.cpp:12: warning: unused variable ‘x’
It's easily fixable by giving the AnonymousClass object an explicit name, but what's going on here and why? I presume that this is more declaration syntax weirdness (like the cases described in Q10.2 and Q10.21 of the comp.lang.C++ FAQ), but I'm not familiar with this one.

AnonymousClass(x);
It defines a variable x of type AnonymousClass. That is why you're getting redefinition error, because x is already declared as int.
The parentheses are superfluous. You can add even more braces like:
AnonymousClass(x);
AnonymousClass((x));
AnonymousClass(((x)));
AnonymousClass((((x))));
//and so on
All of them are same as:
AnonymousClass x;
Demo: http://www.ideone.com/QnRKH
You can use the syntax A(x) to create anonymous object, especially when calling a function:
int x = 10;
f(A(x)); //1 - () is needed
f(A((((x))))); //2 - extra () are superfluous
Both line 1 and 2 call a function f passing an object of type A :
http://www.ideone.com/ofbpR
But again, the extra parentheses are still superfluous at line 2.

You're missing an actual name for your variable/object:
AnonymousClass myclass(x);
Instead of that you could as well write...
AnonymousClass (myclass)(x);
So your line of code results in this:
AnonymousClass (x);
Or more common:
AnonymousClass x;
Why it happens? Brackets are just there for logical grouping ("what belongs together?"). The only difference is, they're forced for arguments (i.e. you can't just write AnonymousClass myclass x).

To avoid such a mistake, just remember one rule: If you declare an anonymous object with one argument, just place it into a pair of parentheses!

Related

Declaration of reference variable requires an initializer

I have reduced my real program to a toy example.
Say I have the following code:
struct A
{
A( string i ) { }
A( string *i ) { }
};
int main()
{
string s;
A("HELLO"); // Works
A(&s); // XCode: Declaration of reference variable 's' requires an initializer
// Visual Studio: error C2040: 's': 'A &' differs in levels of indirection from 'std::string'
}
I don't understand the error message. What does XCode mean "Declaration of reference variable 's' requires an initializer"? Why does A("HELLO"); work while A(&s) does not?
This is a phenomenon called most-vexing parse.
C++ treats A(&s); as a declaration of a variabled called s, whose type is A&. This won't work for several reasons:
References need to be initialized, and you are not initializing s in this example (note: this s is not the same s as the one from 2 lines before).
You already have a variable called s in the same scope, so this would be a redefinition.
To create an even smaller example, take a look at these two, equivalent lines of code that both declare a variable called x of type int:
int x;
int(x);
To fix the issue, you can simply use a proper declaration that uses the desired constructor, which doesn't suffer from the most-vexing parse problem:
A x1(&s); // this
auto x2 = A(&s); // or this
A{&s}; // or this, just to create a temporary

Calling class constructor with parameter - request of a member in 'x' which is of non-class type

I have a class A that accepts class B as a constructor parameter. Class B can be constructed from int value. My original code is quite complex, but I hope I've reduced it to the very base case:
class B {
public:
explicit B(int a) : val(a) {}
private:
int val;
};
class A {
public:
A(const B & val) : value(val) {};
void print() {
//does nothing
}
private:
B value;
};
int main() {
int someTimeVar = 22;
A a(B(someTimeVar));
a.print();
}
And this is the error code I'm getting:
$ g++ test.cpp -Wall -O0
test.cpp: In function ‘int main()’:
test.cpp:22:7: error: request for member ‘print’ in ‘a’, which is of non-class type ‘A(B)’
a.print();
^
test.cpp:20:9: warning: unused variable ‘someTimeVar’ [-Wunused-variable]
int someTimeVar = 22;
^
I use GCC (4.9.2 20150304 (prerelease)), platform: arch linux.
The following modification to the main function compiles fine:
int main() {
A a(B(22));
a.print();
}
I'm well aware that using A a(); declares a function, not a object. But I didn't expect that A a(B(some_val)) will do the same, and in my opinion this is what's happening here.
Do you have ideas why this is happening?
Edit: Thank you for all the answers, looks like I need to research more on most vexing parse idea.
BTW it turns out that compiling my code using clang provides more useful error message plus a solution:
$ clang test.cpp
test.cpp:21:8: warning: parentheses were disambiguated as a function declaration [-Wvexing-parse]
A a(B(someTimeVar));
^~~~~~~~~~~~~~~~
test.cpp:21:9: note: add a pair of parentheses to declare a variable
A a(B(someTimeVar));
^
( )
test.cpp:22:6: error: member reference base type 'A (B)' is not a structure or union
a.print();
~^~~~~~
1 warning and 1 error generated.
A a(B(someTimeVar)) is interpreted as A a(B someTimeVar), so a is a function taking parameter of type B and returning A.
This is one of the reasons the uniform initialization was added to C++11:
A a{B{someTimeVar}};
This problem has its own tag here on stackoverflow. most-vexing-parse
Wikipedia har a clear description of the problem and its solution. https://en.wikipedia.org/wiki/Most_vexing_parse.
The line
TimeKeeper time_keeper(Timer());
could be disambiguated either as
a variable definition for variable time_keeper of class TimeKeeper, passed an anonymous instance of class Timer or
a function declaration for a function time_keeper which returns an object of type TimeKeeper and has a single (unnamed) parameter which
is a function returning type Timer (and taking no input). (See
Function object#In C and C++)
Most programmers expect the first, but the C++ standard requires it to
be interpreted as the second.
The solution is to add parenthesis to the argument like:
A a( (B(22)) );
or as others have noted use universal initialization like
A a { B{22} };
A a(B(someTimeVar)); declares a function with the return type A and one argument of type B named someTimeVar. It's the same as A a(B someTimeVar);
It works in A a(B(22)); because 22 is not a valid identifier, so the functio declaration would be invalid.
If your codebase uses C++11 (or newer), you can use uniform initialization with curly braces: A a(B{someTimeVar});

Inline member initializer containing pointer to member

At work, I'm experimenting a bit to bring some reflection into our codebase. Basically what I want to achieve, is to capture a pointer to data-member inside the type of the data-member's initializer:
template<class Class, int Class::*dataMember>
struct Reflect
{
operator int() {return 0;}
};
class Foo
{
public:
int bar = Reflect<Foo, &Foo::bar>{};
};
Although clang 3.4.1 (http://gcc.godbolt.org/) and Intel C++ XE 14.0 are able to compile this piece of code, when using MSVC12 I get the following error message:
error C2065: 'bar' : undeclared identifier
error C2975: 'dataMember' : invalid template argument for 'Reflect', expected compile-time constant expression
Furthermore, gcc 4.9.2 also seems to have trouble with it: http://ideone.com/ZUVOMO.
So my questions are:
Is the above piece of code valid C++11?
If yes, are there any work arounds for the failing compilers?
What VC++ complains about is certainly not a problem; [basic.scope.pdecl]/1,6:
The point of declaration for a name is immediately after its complete
declarator (Clause 8) and before its initializer (if any), except as
noted below.[…]
After the point of declaration of a class member, the member name can
be looked up in the scope of its class.
This implies that the name lookup is fine. However, as pointed out by #hvd in the comments, there are certain ambiguities in the grammar of such constructs.
Presumably GCC parses the above line until the comma:
int bar = Reflect<Foo,
// at this point Reflect < Foo can be a perfectly fine relational-expression.
// stuff after the comma could be a declarator for a second member.
And bails out once the rest is encountered.
A workaround that makes GCC happy is
int bar = decltype( Reflect<Foo, &Foo::bar>{} )();
Demo. This does not help with VC++ though, which apparently confuses the point of declaration as indicated by the error message.
Thus moving the initializer into a constructor will work:
int bar;
Foo() : bar( Reflect<Foo, &Foo::bar>{} ) {}
// (also works for GCC)
... while providing an initializer at the declaration of bar cannot. Demo #2 on rextester.

function returning a struct in c++?

I am trying to implement a function that returns a struct, but when I compile, it always gives me error.
In my header file:
class AcquireSaveInfo
{
private:
typedef struct
{
double x,y,z;
}resolution;
public:
resolution AddResolutionInfo();
};
in my cpp file:
resolution AcquireSaveInfo::AddResolutionInfo()
{
resolution res;
res.x = 0;
return res;
}
The error messages:
>.\AcquireSaveInfo.cpp(200) : error C2143: syntax error : missing ';' before 'AcquireSaveInfo::AddResolutionInfo'
3>.\AcquireSaveInfo.cpp(200) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
3>.\AcquireSaveInfo.cpp(201) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
3>.\AcquireSaveInfo.cpp(201) : error C2556: 'int AcquireSaveInfo::AddResolutionInfo(void)' : overloaded function differs only by return type from 'AcquireSaveInfo::resolution AcquireSaveInfo::AddResolutionInfo(void)'
3> c:\devolpment\commands\acquisition\runsample\runsample\AcquireSaveInfo.h(39) : see declaration of 'AcquireSaveInfo::AddResolutionInfo'
3>.\AcquireSaveInfo.cpp(201) : error C2371: 'AcquireSaveInfo::AddResolutionInfo' : redefinition; different basic types
I am wondering what is the problem with this? Thanks.
At the point of the function definition resolution is not known.
To overcome this issue, you should add the full scope resolution to the return type.
AcquireSaveInfo::resolution AcquireSaveInfo::AddResolutionInfo()
{
...
}
Alternatively, if your compiler complies to the newest C++11 standard, you could use the trailing return type declaration, for which case the full scope resolution is not required.
auto AcquireSaveInfo::AddResolutionInfo() -> resolution
{
...
}
You should also note resolution is a private type, that means outside the scope of AcquireSaveInfo, it will not be possible to explicitly declare an object of that type to receive the return value of AddResolutionInfo. If, however, you are again using a compiler complying to the C++11 standard, you could still implicitly declare an object of type resolution using the auto keyword.
AcquireSaveInfo a;
auto r = a.AddResolutionInfo();
You need a semicolon at the end of AcquireSaveInfo, like so
class AcquireSaveInfo
{
private:
typedef struct
{
double x,y,z;
}resolution;
public:
resolution AddResolutionInfo();
};
You have the resolution structure declared as private. Thus, if you attempt to return it from a public function, you will get an error because you cannot access the struct. (Example)
You can get around this by either declaring the struct in the public section of the class, or declare it outside the class entirely. In most cases, the latter would be preferred to making it a sub-class.
You made three mistakes
The first is that you forgot to place a semicolon after the closing brace of the class definition.
The second is that you did not specify qualified name for the return type of the function.
And the third error is that the only way to use return value of the function is to use type specifier auto because type AcquireSaveInfo::resolution is private. If your compiler does not support this type specifier then there is no possibility to use the return value of the function.

C++ enum not properly recognized by compiler

Can anyone explain why the following code does not compile (on g++ (GCC) 3.2.3 20030502 (Red Hat Linux 3.2.3-49))?
struct X {
public:
enum State { A, B, C };
X(State s) {}
};
int main()
{
X(X::A);
}
The message I get is:
jjj.cpp: In function 'int main()':
jjj.cpp:10: 'X X::A' is not a static member of 'struct X'
jjj.cpp:10: no matching function for call to 'X::X()'
jjj.cpp:1: candidates are: X::X(const X&)
jjj.cpp:5: X::X(X::State)`
Is this bad code or a compiler bug?
Problem solved by Neil+Konrad. See the comments to Neil's answer below.
You've forgot the variable name in your definition:
int main()
{
X my_x(X::A);
}
Your code confuses the compiler because syntactically it can't distinguish this from a function declaration (returning X and passing X::A as an argument). When in doubt, the C++ compiler always disambiguates in favour of a declaration.
The solution is to introduce redundant parentheses around the X since the compiler forbids parentheses around types (as opposed to constructo calls etc.):
(X(X::A));
X(X::A);
is being seen a s a function declaration. If you really want this code, use:
(X)(X::A);
Just to make it crystal clear what happens. Look at this example
int main() {
float a = 0;
{
int(a); // no-op?
a = 1;
}
cout << a;
}
What will it output? Well, it will output 0. The int(a) of above can be parsed in two different ways:
Cast to int and discard the result
Declare a variable called a. But ignore the parentheses around the identifier.
The compiler, when such a situation appears where a function-style cast is used in a statement and it looks like a declaration too, will always take it as a declaration. When it can't syntactically be a declaration (the compiler will look at the whole line to determine that), it will be taken to be an expression. Thus we are assigning to the inner a above, leaving the outer a at zero.
Now, your case is exactly that. You are trying (accidentally) to declare an identifier called A within a class called X:
X (X::A); // parsed as X X::A;
The compiler then goes on to moan about a not declared default constructor, because the static, as it assumes it to be, is default constructed. But even if you had a default constructor for X, it of course is still wrong because neither A is a static member of X, nor a static of X can be defined/declared at block scope.
You can make it not look like a declaration by doing several things. First, you can paren the whole expression, which makes it not look like a declaration anymore. Or just paren the type that is cast to. Both of these disambiguations have been mentioned in other answers:
(X(X::A)); (X)(X::A)
There is a similar, but distinct ambiguity when you try to actually declare an object. Look at this example:
int main() {
float a = 0;
int b(int(a)); // object or function?
}
Because int(a) can be both the declaration of a parameter called a and the explicit conversion (cast) of the float-variable to an int, the compiler decides again that that is a declaration. Thus, we happen to declare a function called b, which takes an integer argument and returns an integer. There are several possibilities how to disambiguate that, based on the disambiguation of above:
int b((int(a))); int b((int)a);
You should declare an object as
X x(X::A);
Bug in your code.
Either of these two lines work for me:
X obj(X::A);
X obj2 = X(X::A);
As Neil Butterworth points out, X(X::A) is being treated as a function declaration. If you really want an anonymous object, (X)(X::A) will construct an X object and immediately delete it.
You could, of course, just do something like this:
int main()
{
// code
{
X temp(X::A);
}
// more code
}
This would be more readable and basically have the same effect.