A confusing detail about the Most Vexing Parse - c++

My question is how the following line can be parsed as a function declaration:
vector<int> v(istream_iterator<int>(cin), istream_iterator<int>());
I understand most of the details of the Most Vexing Parse and why the second temporary iterator can be interpreted as a type that is a function returning an iterator and taking no arguments, but what I don't get is why the first temporary iterator can be interpreted as a type. What type does it represent? My thought is that it would be some sort of function type, but I can't see how the name cin gets used. Is it declaring that the parameter is an istream_iterator<int> named cin? If so, does that mean that you can arbitrarily parenthesize the names of arguments to functions? And if so, why?

istream_iterator<int>(cin) is exactly the same as istream_iterator<int> cin but with superfluous parens. This declarator syntax was inherited from C, and I think even the inventor of C (Ken Thompson?) described it as a mistake.

Did I already said that I liked Clang (a lot) ?
Just try the following (simplified code)
#include <vector>
void foo(std::vector<int>);
int main() {
std::vector<int> v(int(i), int());
foo(v);
}
In the newly rebrandished LLVM Try Out (well, it just went from llvm-gcc to clang).
And you get:
/tmp/webcompile/_21483_0.cc:6:21: warning: parentheses were disambiguated
as a function declarator
std::vector<int> v(int(i), int());
^~~~~~~~~~~~~~~
/tmp/webcompile/_21483_0.cc:7:3: error: no matching function for call to 'foo'
foo(v);
^~~
/tmp/webcompile/_21483_0.cc:3:6: note: candidate function not viable:
no known conversion from 'std::vector<int> (int, int (*)())'
to 'std::vector<int>' for 1st argument
void foo(std::vector<int>);
^
3 diagnostics generated.
And therefore, #john is right, int(i) is interpreted as int i, ie a named parameter to the function.

Yes, it is the parameter name. And, yes you can add a set of parenthesis, because sometimes you have to.
If the parameter is a function pointer, void (*f)() you need to write it like that.
The people writing the standard have not spent their precious time pointing out exactly the cases where the parenthesis are allowed or actually required, so the standard just says that you can have them.

There is a section called Ambiguity resolution in the Standard (2003) which is dedicated to such syntaxes. I think I don't need to explain it further if you read the section yourself, for its very clear with lots of examples!
So here you go:
8.2 Ambiguity resolution [dcl.ambig.res]
1 - The ambiguity arising from the similarity between a function-style cast and a declaration mentioned in 6.8 can also occur in the context of a declaration. In that context, the choice is between a function declaration with a redundant set of parentheses around a parameter name and an object declaration with a function-style cast as the initializer. Just as for the ambiguities mentioned in 6.8, the resolution is to consider any construct that could possibly be a declaration a declaration. [Note: a declaration can be explicitly disambiguated by a nonfunction-style cast, by a = to indicate initialization or by removing the redundant parentheses around the parameter name. ]
[Example:
struct S {
S(int);
};
void foo(double a)
{
S w(int(a)); // function declaration
S x(int()); // function declaration
S y((int)a); // object declaration
S z = int(a); // object declaration
}
—end example]
2 - The ambiguity arising from the similarity between a function-style cast and a type-id can occur in different contexts. The ambiguity appears as a choice between a function-style cast expression and a declaration of a type. The resolution is that any construct that could possibly be a type-id in its syntactic context shall be considered a type-id.
3- [Example:
#include <cstddef>
char *p;
void *operator new(size_t, int);
void foo() {
const int x = 63;
new (int(*p)) int; // new-placement expression
new (int(*[x])); // new type-id
}
//4 - For another example,
template <class T>
struct S {
T *p;
};
S<int()> x; // type-id
S<int(1)> y; // expression (ill-formed)
//5 - For another example,
void foo()
{
sizeof(int(1)); // expression
sizeof(int()); // type-id (ill-formed)
}
//6 - For another example,
void foo()
{
(int(1)); //expression
(int())1; //type-id (ill-formed)
}
—end example]
7 - Another ambiguity arises in a parameter-declaration-clause of a function declaration, or in a type-id that is the operand of a sizeof or typeid operator, when a type-name is nested in parentheses. In this case, the choice is between the declaration of a parameter of type pointer to function and the declaration of a parameter with redundant parentheses around the declarator-id. The resolution is to consider the type-name as a
simple-type-specifier rather than a declarator-id.
[Example:
class C { };
void f(int(C)) { } // void f(int (*fp)(C c)) { }
// not: void f(int C);
int g(C);
void foo() {
f(1); //error: cannot convert 1 to function pointer
f(g); //OK
}
//For another example,
class C { };
void h(int *(C[10])); // void h(int *(*_fp)(C _parm[10]));
// not: void h(int *C[10]);
—end example]

Related

template class default template arguments vs default function arguments [duplicate]

My question is how the following line can be parsed as a function declaration:
vector<int> v(istream_iterator<int>(cin), istream_iterator<int>());
I understand most of the details of the Most Vexing Parse and why the second temporary iterator can be interpreted as a type that is a function returning an iterator and taking no arguments, but what I don't get is why the first temporary iterator can be interpreted as a type. What type does it represent? My thought is that it would be some sort of function type, but I can't see how the name cin gets used. Is it declaring that the parameter is an istream_iterator<int> named cin? If so, does that mean that you can arbitrarily parenthesize the names of arguments to functions? And if so, why?
istream_iterator<int>(cin) is exactly the same as istream_iterator<int> cin but with superfluous parens. This declarator syntax was inherited from C, and I think even the inventor of C (Ken Thompson?) described it as a mistake.
Did I already said that I liked Clang (a lot) ?
Just try the following (simplified code)
#include <vector>
void foo(std::vector<int>);
int main() {
std::vector<int> v(int(i), int());
foo(v);
}
In the newly rebrandished LLVM Try Out (well, it just went from llvm-gcc to clang).
And you get:
/tmp/webcompile/_21483_0.cc:6:21: warning: parentheses were disambiguated
as a function declarator
std::vector<int> v(int(i), int());
^~~~~~~~~~~~~~~
/tmp/webcompile/_21483_0.cc:7:3: error: no matching function for call to 'foo'
foo(v);
^~~
/tmp/webcompile/_21483_0.cc:3:6: note: candidate function not viable:
no known conversion from 'std::vector<int> (int, int (*)())'
to 'std::vector<int>' for 1st argument
void foo(std::vector<int>);
^
3 diagnostics generated.
And therefore, #john is right, int(i) is interpreted as int i, ie a named parameter to the function.
Yes, it is the parameter name. And, yes you can add a set of parenthesis, because sometimes you have to.
If the parameter is a function pointer, void (*f)() you need to write it like that.
The people writing the standard have not spent their precious time pointing out exactly the cases where the parenthesis are allowed or actually required, so the standard just says that you can have them.
There is a section called Ambiguity resolution in the Standard (2003) which is dedicated to such syntaxes. I think I don't need to explain it further if you read the section yourself, for its very clear with lots of examples!
So here you go:
8.2 Ambiguity resolution [dcl.ambig.res]
1 - The ambiguity arising from the similarity between a function-style cast and a declaration mentioned in 6.8 can also occur in the context of a declaration. In that context, the choice is between a function declaration with a redundant set of parentheses around a parameter name and an object declaration with a function-style cast as the initializer. Just as for the ambiguities mentioned in 6.8, the resolution is to consider any construct that could possibly be a declaration a declaration. [Note: a declaration can be explicitly disambiguated by a nonfunction-style cast, by a = to indicate initialization or by removing the redundant parentheses around the parameter name. ]
[Example:
struct S {
S(int);
};
void foo(double a)
{
S w(int(a)); // function declaration
S x(int()); // function declaration
S y((int)a); // object declaration
S z = int(a); // object declaration
}
—end example]
2 - The ambiguity arising from the similarity between a function-style cast and a type-id can occur in different contexts. The ambiguity appears as a choice between a function-style cast expression and a declaration of a type. The resolution is that any construct that could possibly be a type-id in its syntactic context shall be considered a type-id.
3- [Example:
#include <cstddef>
char *p;
void *operator new(size_t, int);
void foo() {
const int x = 63;
new (int(*p)) int; // new-placement expression
new (int(*[x])); // new type-id
}
//4 - For another example,
template <class T>
struct S {
T *p;
};
S<int()> x; // type-id
S<int(1)> y; // expression (ill-formed)
//5 - For another example,
void foo()
{
sizeof(int(1)); // expression
sizeof(int()); // type-id (ill-formed)
}
//6 - For another example,
void foo()
{
(int(1)); //expression
(int())1; //type-id (ill-formed)
}
—end example]
7 - Another ambiguity arises in a parameter-declaration-clause of a function declaration, or in a type-id that is the operand of a sizeof or typeid operator, when a type-name is nested in parentheses. In this case, the choice is between the declaration of a parameter of type pointer to function and the declaration of a parameter with redundant parentheses around the declarator-id. The resolution is to consider the type-name as a
simple-type-specifier rather than a declarator-id.
[Example:
class C { };
void f(int(C)) { } // void f(int (*fp)(C c)) { }
// not: void f(int C);
int g(C);
void foo() {
f(1); //error: cannot convert 1 to function pointer
f(g); //OK
}
//For another example,
class C { };
void h(int *(C[10])); // void h(int *(*_fp)(C _parm[10]));
// not: void h(int *C[10]);
—end example]

How Can I initialize a vector of integers directly from a range of elements denoted by input-stream-iterators? [duplicate]

My question is how the following line can be parsed as a function declaration:
vector<int> v(istream_iterator<int>(cin), istream_iterator<int>());
I understand most of the details of the Most Vexing Parse and why the second temporary iterator can be interpreted as a type that is a function returning an iterator and taking no arguments, but what I don't get is why the first temporary iterator can be interpreted as a type. What type does it represent? My thought is that it would be some sort of function type, but I can't see how the name cin gets used. Is it declaring that the parameter is an istream_iterator<int> named cin? If so, does that mean that you can arbitrarily parenthesize the names of arguments to functions? And if so, why?
istream_iterator<int>(cin) is exactly the same as istream_iterator<int> cin but with superfluous parens. This declarator syntax was inherited from C, and I think even the inventor of C (Ken Thompson?) described it as a mistake.
Did I already said that I liked Clang (a lot) ?
Just try the following (simplified code)
#include <vector>
void foo(std::vector<int>);
int main() {
std::vector<int> v(int(i), int());
foo(v);
}
In the newly rebrandished LLVM Try Out (well, it just went from llvm-gcc to clang).
And you get:
/tmp/webcompile/_21483_0.cc:6:21: warning: parentheses were disambiguated
as a function declarator
std::vector<int> v(int(i), int());
^~~~~~~~~~~~~~~
/tmp/webcompile/_21483_0.cc:7:3: error: no matching function for call to 'foo'
foo(v);
^~~
/tmp/webcompile/_21483_0.cc:3:6: note: candidate function not viable:
no known conversion from 'std::vector<int> (int, int (*)())'
to 'std::vector<int>' for 1st argument
void foo(std::vector<int>);
^
3 diagnostics generated.
And therefore, #john is right, int(i) is interpreted as int i, ie a named parameter to the function.
Yes, it is the parameter name. And, yes you can add a set of parenthesis, because sometimes you have to.
If the parameter is a function pointer, void (*f)() you need to write it like that.
The people writing the standard have not spent their precious time pointing out exactly the cases where the parenthesis are allowed or actually required, so the standard just says that you can have them.
There is a section called Ambiguity resolution in the Standard (2003) which is dedicated to such syntaxes. I think I don't need to explain it further if you read the section yourself, for its very clear with lots of examples!
So here you go:
8.2 Ambiguity resolution [dcl.ambig.res]
1 - The ambiguity arising from the similarity between a function-style cast and a declaration mentioned in 6.8 can also occur in the context of a declaration. In that context, the choice is between a function declaration with a redundant set of parentheses around a parameter name and an object declaration with a function-style cast as the initializer. Just as for the ambiguities mentioned in 6.8, the resolution is to consider any construct that could possibly be a declaration a declaration. [Note: a declaration can be explicitly disambiguated by a nonfunction-style cast, by a = to indicate initialization or by removing the redundant parentheses around the parameter name. ]
[Example:
struct S {
S(int);
};
void foo(double a)
{
S w(int(a)); // function declaration
S x(int()); // function declaration
S y((int)a); // object declaration
S z = int(a); // object declaration
}
—end example]
2 - The ambiguity arising from the similarity between a function-style cast and a type-id can occur in different contexts. The ambiguity appears as a choice between a function-style cast expression and a declaration of a type. The resolution is that any construct that could possibly be a type-id in its syntactic context shall be considered a type-id.
3- [Example:
#include <cstddef>
char *p;
void *operator new(size_t, int);
void foo() {
const int x = 63;
new (int(*p)) int; // new-placement expression
new (int(*[x])); // new type-id
}
//4 - For another example,
template <class T>
struct S {
T *p;
};
S<int()> x; // type-id
S<int(1)> y; // expression (ill-formed)
//5 - For another example,
void foo()
{
sizeof(int(1)); // expression
sizeof(int()); // type-id (ill-formed)
}
//6 - For another example,
void foo()
{
(int(1)); //expression
(int())1; //type-id (ill-formed)
}
—end example]
7 - Another ambiguity arises in a parameter-declaration-clause of a function declaration, or in a type-id that is the operand of a sizeof or typeid operator, when a type-name is nested in parentheses. In this case, the choice is between the declaration of a parameter of type pointer to function and the declaration of a parameter with redundant parentheses around the declarator-id. The resolution is to consider the type-name as a
simple-type-specifier rather than a declarator-id.
[Example:
class C { };
void f(int(C)) { } // void f(int (*fp)(C c)) { }
// not: void f(int C);
int g(C);
void foo() {
f(1); //error: cannot convert 1 to function pointer
f(g); //OK
}
//For another example,
class C { };
void h(int *(C[10])); // void h(int *(*_fp)(C _parm[10]));
// not: void h(int *C[10]);
—end example]

Prototyped function warning when constructing an object with a cast argument [duplicate]

My question is how the following line can be parsed as a function declaration:
vector<int> v(istream_iterator<int>(cin), istream_iterator<int>());
I understand most of the details of the Most Vexing Parse and why the second temporary iterator can be interpreted as a type that is a function returning an iterator and taking no arguments, but what I don't get is why the first temporary iterator can be interpreted as a type. What type does it represent? My thought is that it would be some sort of function type, but I can't see how the name cin gets used. Is it declaring that the parameter is an istream_iterator<int> named cin? If so, does that mean that you can arbitrarily parenthesize the names of arguments to functions? And if so, why?
istream_iterator<int>(cin) is exactly the same as istream_iterator<int> cin but with superfluous parens. This declarator syntax was inherited from C, and I think even the inventor of C (Ken Thompson?) described it as a mistake.
Did I already said that I liked Clang (a lot) ?
Just try the following (simplified code)
#include <vector>
void foo(std::vector<int>);
int main() {
std::vector<int> v(int(i), int());
foo(v);
}
In the newly rebrandished LLVM Try Out (well, it just went from llvm-gcc to clang).
And you get:
/tmp/webcompile/_21483_0.cc:6:21: warning: parentheses were disambiguated
as a function declarator
std::vector<int> v(int(i), int());
^~~~~~~~~~~~~~~
/tmp/webcompile/_21483_0.cc:7:3: error: no matching function for call to 'foo'
foo(v);
^~~
/tmp/webcompile/_21483_0.cc:3:6: note: candidate function not viable:
no known conversion from 'std::vector<int> (int, int (*)())'
to 'std::vector<int>' for 1st argument
void foo(std::vector<int>);
^
3 diagnostics generated.
And therefore, #john is right, int(i) is interpreted as int i, ie a named parameter to the function.
Yes, it is the parameter name. And, yes you can add a set of parenthesis, because sometimes you have to.
If the parameter is a function pointer, void (*f)() you need to write it like that.
The people writing the standard have not spent their precious time pointing out exactly the cases where the parenthesis are allowed or actually required, so the standard just says that you can have them.
There is a section called Ambiguity resolution in the Standard (2003) which is dedicated to such syntaxes. I think I don't need to explain it further if you read the section yourself, for its very clear with lots of examples!
So here you go:
8.2 Ambiguity resolution [dcl.ambig.res]
1 - The ambiguity arising from the similarity between a function-style cast and a declaration mentioned in 6.8 can also occur in the context of a declaration. In that context, the choice is between a function declaration with a redundant set of parentheses around a parameter name and an object declaration with a function-style cast as the initializer. Just as for the ambiguities mentioned in 6.8, the resolution is to consider any construct that could possibly be a declaration a declaration. [Note: a declaration can be explicitly disambiguated by a nonfunction-style cast, by a = to indicate initialization or by removing the redundant parentheses around the parameter name. ]
[Example:
struct S {
S(int);
};
void foo(double a)
{
S w(int(a)); // function declaration
S x(int()); // function declaration
S y((int)a); // object declaration
S z = int(a); // object declaration
}
—end example]
2 - The ambiguity arising from the similarity between a function-style cast and a type-id can occur in different contexts. The ambiguity appears as a choice between a function-style cast expression and a declaration of a type. The resolution is that any construct that could possibly be a type-id in its syntactic context shall be considered a type-id.
3- [Example:
#include <cstddef>
char *p;
void *operator new(size_t, int);
void foo() {
const int x = 63;
new (int(*p)) int; // new-placement expression
new (int(*[x])); // new type-id
}
//4 - For another example,
template <class T>
struct S {
T *p;
};
S<int()> x; // type-id
S<int(1)> y; // expression (ill-formed)
//5 - For another example,
void foo()
{
sizeof(int(1)); // expression
sizeof(int()); // type-id (ill-formed)
}
//6 - For another example,
void foo()
{
(int(1)); //expression
(int())1; //type-id (ill-formed)
}
—end example]
7 - Another ambiguity arises in a parameter-declaration-clause of a function declaration, or in a type-id that is the operand of a sizeof or typeid operator, when a type-name is nested in parentheses. In this case, the choice is between the declaration of a parameter of type pointer to function and the declaration of a parameter with redundant parentheses around the declarator-id. The resolution is to consider the type-name as a
simple-type-specifier rather than a declarator-id.
[Example:
class C { };
void f(int(C)) { } // void f(int (*fp)(C c)) { }
// not: void f(int C);
int g(C);
void foo() {
f(1); //error: cannot convert 1 to function pointer
f(g); //OK
}
//For another example,
class C { };
void h(int *(C[10])); // void h(int *(*_fp)(C _parm[10]));
// not: void h(int *C[10]);
—end example]

C++ vector, initialization from istream_iterator why do I have to use braced list initialization? [duplicate]

My question is how the following line can be parsed as a function declaration:
vector<int> v(istream_iterator<int>(cin), istream_iterator<int>());
I understand most of the details of the Most Vexing Parse and why the second temporary iterator can be interpreted as a type that is a function returning an iterator and taking no arguments, but what I don't get is why the first temporary iterator can be interpreted as a type. What type does it represent? My thought is that it would be some sort of function type, but I can't see how the name cin gets used. Is it declaring that the parameter is an istream_iterator<int> named cin? If so, does that mean that you can arbitrarily parenthesize the names of arguments to functions? And if so, why?
istream_iterator<int>(cin) is exactly the same as istream_iterator<int> cin but with superfluous parens. This declarator syntax was inherited from C, and I think even the inventor of C (Ken Thompson?) described it as a mistake.
Did I already said that I liked Clang (a lot) ?
Just try the following (simplified code)
#include <vector>
void foo(std::vector<int>);
int main() {
std::vector<int> v(int(i), int());
foo(v);
}
In the newly rebrandished LLVM Try Out (well, it just went from llvm-gcc to clang).
And you get:
/tmp/webcompile/_21483_0.cc:6:21: warning: parentheses were disambiguated
as a function declarator
std::vector<int> v(int(i), int());
^~~~~~~~~~~~~~~
/tmp/webcompile/_21483_0.cc:7:3: error: no matching function for call to 'foo'
foo(v);
^~~
/tmp/webcompile/_21483_0.cc:3:6: note: candidate function not viable:
no known conversion from 'std::vector<int> (int, int (*)())'
to 'std::vector<int>' for 1st argument
void foo(std::vector<int>);
^
3 diagnostics generated.
And therefore, #john is right, int(i) is interpreted as int i, ie a named parameter to the function.
Yes, it is the parameter name. And, yes you can add a set of parenthesis, because sometimes you have to.
If the parameter is a function pointer, void (*f)() you need to write it like that.
The people writing the standard have not spent their precious time pointing out exactly the cases where the parenthesis are allowed or actually required, so the standard just says that you can have them.
There is a section called Ambiguity resolution in the Standard (2003) which is dedicated to such syntaxes. I think I don't need to explain it further if you read the section yourself, for its very clear with lots of examples!
So here you go:
8.2 Ambiguity resolution [dcl.ambig.res]
1 - The ambiguity arising from the similarity between a function-style cast and a declaration mentioned in 6.8 can also occur in the context of a declaration. In that context, the choice is between a function declaration with a redundant set of parentheses around a parameter name and an object declaration with a function-style cast as the initializer. Just as for the ambiguities mentioned in 6.8, the resolution is to consider any construct that could possibly be a declaration a declaration. [Note: a declaration can be explicitly disambiguated by a nonfunction-style cast, by a = to indicate initialization or by removing the redundant parentheses around the parameter name. ]
[Example:
struct S {
S(int);
};
void foo(double a)
{
S w(int(a)); // function declaration
S x(int()); // function declaration
S y((int)a); // object declaration
S z = int(a); // object declaration
}
—end example]
2 - The ambiguity arising from the similarity between a function-style cast and a type-id can occur in different contexts. The ambiguity appears as a choice between a function-style cast expression and a declaration of a type. The resolution is that any construct that could possibly be a type-id in its syntactic context shall be considered a type-id.
3- [Example:
#include <cstddef>
char *p;
void *operator new(size_t, int);
void foo() {
const int x = 63;
new (int(*p)) int; // new-placement expression
new (int(*[x])); // new type-id
}
//4 - For another example,
template <class T>
struct S {
T *p;
};
S<int()> x; // type-id
S<int(1)> y; // expression (ill-formed)
//5 - For another example,
void foo()
{
sizeof(int(1)); // expression
sizeof(int()); // type-id (ill-formed)
}
//6 - For another example,
void foo()
{
(int(1)); //expression
(int())1; //type-id (ill-formed)
}
—end example]
7 - Another ambiguity arises in a parameter-declaration-clause of a function declaration, or in a type-id that is the operand of a sizeof or typeid operator, when a type-name is nested in parentheses. In this case, the choice is between the declaration of a parameter of type pointer to function and the declaration of a parameter with redundant parentheses around the declarator-id. The resolution is to consider the type-name as a
simple-type-specifier rather than a declarator-id.
[Example:
class C { };
void f(int(C)) { } // void f(int (*fp)(C c)) { }
// not: void f(int C);
int g(C);
void foo() {
f(1); //error: cannot convert 1 to function pointer
f(g); //OK
}
//For another example,
class C { };
void h(int *(C[10])); // void h(int *(*_fp)(C _parm[10]));
// not: void h(int *C[10]);
—end example]

Invalid object after elision of copy operation? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why is it an error to use an empty set of brackets to call a constructor with no arguments?
Most vexing parse: why doesn't A a(()); work?
This one gets me mad. Maybe its just too simple.
struct Foo
{
Foo() {}
Foo(const Foo& f) {}
void work() {}
};
int main()
{
Foo f( Foo() );
f.work();
}
GCC 4.6 gives me:
error: request for member ‘work’ in ‘f’, which is of non-class type ‘Foo(Foo (*)())’
After elision of the copy operation the effective code might look like:
int main()
{
Foo f;
f.work();
}
But why can't i call work() ??
Edit:
Yes, duplicate (see below). Didn't find the original post when search first because the source of the symptoms of this is located where i didn't expect that.
Because Foo f( Foo() ); is a function declaration.
I think you want: Foo f;
Or in case you want to copy-construct:
Foo f( (Foo()) );
f is effectively a function declaration within main function.
Try
Foo f((Foo())); // to make the definition of f explicit enough.
n3337 8.2
The ambiguity arising from the similarity between a function-style
cast and a declaration mentioned in 6.8 can also occur in the context
of a declaration. In that context, the choice is between a function
declaration with a redundant set of parentheses around a parameter
name and an object declaration with a function-style cast as the
initializer. Just as for the ambiguities mentioned in 6.8, the
resolution is to consider any construct that could possibly be a
declaration a declaration. [ Note: A declaration can be explicitly
disambiguated by a nonfunction-style cast, by an = to indicate
initialization or by removing the redundant parentheses around the
parameter name. — end note ] [ Example:
struct S {
S(int);
};
void foo(double a) {
S w(int(a));
//function declaration
S x(int());
//function declaration
S y((int)a);
//object declaration
S z = int(a);
//object declaration
}
— end example ]
C++ parser interprets Foo f(Foo()); expression as the function declaration with the signature Foo(Foo(*)()), i.e. a function returning Foo and taking a function pointer to the function returning Foo. Adding explicit parenthesis around the argument like so Foo f((Foo())); will resolve the ambiguity. But consider actually just doing Foo f; which avoids redundant code.