Compiler complains about BOOST_CHECK_THROW on constructor - c++

The following does not compile:
class Foo {
public:
Foo( boost::shared_ptr< Bar > arg );
};
// in test-case
boost::shared_ptr< Bar > bar;
BOOST_CHECK_THROW( Foo( bar ), std::logic_error ); // compiler error here
The implementation of Bar does not matter. The compiler complains, that Foo does not have an appropriate default constructor (VC++ 2005). If I add a default constructor, it works, and it actually gets called. Why does this statement require a default constructor?

This occurs because BOOST_CHECK_THROW is a macro, and Foo(bar) is being expanded to a statement. The compiler sees this statement and interprets it as a variable declaration Foo bar; which requires a default constructor.
The solution is to give the variable a name:
BOOST_CHECK_THROW( Foo temp( bar ), std::logic_error );
In other words BOOST_CHECK_THROW will expand to something like
try
{
Foo(bar);
// ... fail test ...
}
catch( std::logic_error )
{
// ... pass test ...
}
and the compiler is interpreting Foo(bar); as the declaration of a variable called bar. One can check this with a simple program:
struct Test
{
Test(int *x) {}
};
int main()
{
int *x=0;
Test(x);
return 0;
}
which gives the following errors with g++
test.cpp: In function ‘int main()’:
test.cpp:10: error: conflicting declaration ‘Test x’
test.cpp:9: error: ‘x’ has a previous declaration as ‘int* x’

Related

GCC 11.x vexing-parse + inconsistent error (redeclaration as different symbol type), is it a GCC bug?

The following code compiles with no problems from GCC 4.7.1 up to but not including GCC 11.1:
constexpr int SomeValue = 0;
void test () {
void (SomeValue) ();
}
On GCC 11.x it fails with:
<source>:4:23: error: 'void SomeValue()' redeclared as different kind of entity
4 | void (SomeValue) ();
| ^
<source>:1:15: note: previous declaration 'constexpr const int SomeValue'
1 | constexpr int SomeValue = 0;
| ^~~~~~~~~
But the error "redeclared as different kind of entity" seems strange to me: Ambiguous parsing possibilities aside, the scope is different. Also, these tests all compile on all versions of GCC since 4.7.1 (including 11.x), even though AFAIK each one is redeclaring SomeValue as "a different type of entity":
constexpr int SomeValue = 0;
void test1 () { typedef void (SomeValue) (); }
void test2 () { double SomeValue; }
void test3 () { using SomeValue = char *; }
void test4 () { void (* SomeValue) (); }
void test5 () { struct SomeValue { }; }
void test6 () { enum class SomeValue { }; }
As a relatively less nonsensical example, this code also fails from 11.x on in a similar fashion:
constexpr int SomeValue = 0;
struct SomeClass {
explicit SomeClass (int) { }
void operator () () { }
};
void test () {
SomeClass(SomeValue)();
}
Although in this case it's preceded by a vexing-parse warning that also isn't present before 11.x (the fact that the warning is here but not in the above makes sense, the fact that the warning doesn't appear pre-11.x is the interesting bit):
<source>: In function 'void test()':
<source>:9:25: warning: empty parentheses were disambiguated as a function declaration [-Wvexing-parse]
9 | SomeClass(SomeValue)();
| ^~
<source>: At global scope:
<source>:9:26: error: 'SomeClass SomeValue()' redeclared as different kind of entity
9 | SomeClass(SomeValue)();
| ^
<source>:1:15: note: previous declaration 'constexpr const int SomeValue'
1 | constexpr int SomeValue = 0;
| ^~~~~~~~~
Compiler returned: 1
But wait! There's more!
This code -- which I would have expected to fail on 11.x due to the same parsing ambiguities as above -- compiles just fine on all those versions of GCC (including 11.x):
constexpr int SomeValue = 0;
auto closure = [] (int) {
return [] () { };
};
void test () {
closure(SomeValue)(); // <-- doesn't cause any problems
}
No warnings or anything there.
So... What's going on here? Why is it only a problem for SomeValue to be "redeclared as a different kind of entity" in those specific cases, and only since GCC 11.1, and why doesn't closure(SomeValue)() suffer the same problem as SomeClass(SomeValue)()?
Also what changed? Is GCC correct here? Is it a new bug introduced in GCC 11.x? Or perhaps an old bug that was finally fixed in 11.x? Or not a bug at all and something else changed?
I'm struggling to come up with a consistent explanation.
The difference is that your first snippet declares a function that exists globally; all your other declarations are of local entities.
(Note that even if the declaration were valid, you couldn't call that function, since it can't exist.)
In the last snippet, closure is not a type, so it can't be a declaration.

Two-stage templated alias not resolvable in constructor?

I am trying to work with a two-stage templated alias, but I cannot get the alias to be accepted as a constructor parameter. Is there a way to do this?
An example of what I am trying to do is seen in the following code:
#include <memory>
template <typename Bar>
class Foo
{
public:
using FooPtr = std::shared_ptr<Foo<Bar> >;
static FooPtr getFooPtr(Bar someBar) { return std::make_shared<Foo<Bar> >(someBar); }
Foo(Bar bar) : _bar(bar) {}
Bar getBar() { return _bar; }
private:
Bar _bar;
};
template <typename Bar>
class Foobar
{
public:
using FB = Foo<Bar>;
Foobar(FB::FooPtr fooPtr)
: _fooPtr(fooPtr)
{
}
FB::FooPtr getFooPtr() { return _fooPtr; }
private:
FB::FooPtr _fooPtr;
};
int main()
{
Foobar myFoobar<int>(f::getFooPtr(4));
return myFoobar.getFooPtr()->getBar();
}
When I compile this with g++, I get the following:
dev#ubuntu:~/test/fsm$ g++ -std=c++1z test.cpp
test.cpp:23:23: error: expected ‘)’ before ‘fooPtr’
Foobar(FB::FooPtr fooPtr)
^
test.cpp:28:5: error: need ‘typename’ before ‘Foobar<Bar>::FB::FooPtr’ because ‘Foobar<Bar>::FB’ is a dependent scope
FB::FooPtr getFooPtr() { return _fooPtr; }
^
test.cpp:31:5: error: need ‘typename’ before ‘Foobar<Bar>::FB::FooPtr’ because ‘Foobar<Bar>::FB’ is a dependent scope
FB::FooPtr _fooPtr;
^
test.cpp: In function ‘int main()’:
test.cpp:36:11: error: missing template arguments before ‘myFoobar’
Foobar myFoobar<int>(f::getFooPtr(4));
^
test.cpp:37:11: error: ‘myFoobar’ was not declared in this scope
return myFoobar.getFooPtr()->getBar();
Is the compiler not recognizing the alias FB in the Foobar constuctor? Or is it a problem with resolving Foo::FooPtr to a type?
Thanks!

Error: 'xxx' is not a type [duplicate]

This question already has an answer here:
Why can in-class initializers only use = or {}? [duplicate]
(1 answer)
Closed 6 years ago.
In this complete code:
class foo
{
public:
foo(const int pin);
};
class bar {
public:
// Constructor
bar(const int dataPin) : dataPin_ (dataPin) { }
private:
const int dataPin_;
foo myFoo_ (dataPin_); // instance of foo
};
int main (void)
{
return 0;
}
Using g++ 4.8.4 I get the error:
g++ -Wall -c "test.cpp" (in directory: /home/nick/Development)
test.cpp:14:17: error: ‘dataPin_’ is not a type
foo myFoo_ (dataPin_); // instance of foo
^
Compilation failed.
Using clang 3.4-1ubuntu3 I get:
test.cpp:14:17: error: unknown type name 'dataPin_'
foo myFoo_ (dataPin_); // instance of foo
^
1 error generated.
Why does it want a type here? This is attempting to create an instance of foo as a class variable of bar. The variable dataPin_ is declared directly above.
If I change the line with the error to this, it compiles cleanly:
foo myFoo_ (int dataPin_); // instance of foo
It's reading foo myFoo_ (dataPin_); as a function declaration: myFoo_ is a function taking a dataPin_ and returning a foo. That's why it's expecting a type name in ( ).
To fix this, initialize myFoo_ in your constructor, just like you did with dataPin_:
bar(const int dataPin) : dataPin_ (dataPin), myFoo_(dataPin) {}
Here you should add type not variable, this is the function signature, it should has types not variables.
foo myFoo_ (dataPin_); // instance of foo

parsing error invoking static function on object instance?

I'm wondering if the following code should be considered valid c++, gcc and clang both choke on it while Microsoft and the embedded compiler (green hills) our project uses seem to parse this without problems. This line of code gives gcc and clang trouble:
foo().Bar<int>();
It appears gcc thinks the < is a less than operator instead of specifying a template argument. If Bar is changed to not be a template function gcc accepts it.
class Test1
{
public:
template<typename U>
static void Bar() {}
};
template<typename T>
class Test2
{
public:
Test2()
{
foo().Bar<int>();
}
Test1 foo() { return t; }
Test1 t;
};
int main()
{
Test2<int> t;
}
From my research calling a static member function on an object instance is valid c++. So what are you thoughts? Here is gcc's error:
Error.cpp: In constructor ‘Test2<T>::Test2()’:
Error.cpp:14:17: error: expected primary-expression before ‘int’
foo().Bar<int>();
^
Error.cpp:14:17: error: expected ‘;’ before ‘int’
The correct syntax is:
foo().template Bar<int>();
(Adding to #Dieter answer)
Otherwise you have to use a temporary:
Test1 tt = foo();
tt.Bar<int>();
(in this case you could have simply used t instead of tt, but that was not the point, of course).

In C, assignment of function pointer to appropriately-typed variable gives "cannot convert ... in assignment"

Take the following C/C++ code:
#include <stdlib.h>
int inc(int i) { return i+1; } // int→int, like abs()
// baz is bool→(int→int)
int (*baz(bool b))(int) { return b ? &abs : &inc; }
int main() {
int (*foo(bool))(int); // foo is &(bool→(int→int))
foo = baz;
}
Attempting to compile this (gcc or g++) gives:
$ g++ test.cc
test.cc: In function ‘int main()’:
test.cc:9: error: assignment of function ‘int (* foo(bool))(int)’
test.cc:9: error: cannot convert ‘int (*(bool))(int)’ to ‘int (*(bool))(int)’ in assignment
Check for yourself: the two types it claims it cannot convert between are exactly the same. Why then is it claiming that they are incompatible?
EDIT 1: The problem disappears when using typedefs (as is recommended), like so:
int main() {
typedef int (*int2int)(int);
typedef int2int (*bool2_int2int)(bool);
bool2_int2int foo;
foo = baz;
}
EDIT 2: The compiler, of course, was right. The problem with my original code, as many pointed out, is that foo in main() is a declaration of a function, and not a function pointer. The error in the assignment was therefore not conflicting types but assigning to a function, which is not possible. The correct code is:
#include <stdlib.h>
int inc(int i) { return i+1; } // int→int, like abs()
// baz is bool→(int→int)
int (*baz(bool b))(int) { return b ? &abs : &inc; }
int main() {
int (*(*foo)(bool))(int); // foo is &(bool→(int→int))
foo = &baz;
}
The code is in fact wrong. The problem is that this line:
int (*foo(bool))(int); // foo is &(bool→(int→int))
... doesn't mean what you think it means. It's interpreted as a declaration of a function named "foo". That makes perfect sense. Think about it - if you had wanted to forward declare "baz", you would have put int (*baz(bool))(int); , right? Also, since baz is a function which returns a function pointer, and foo is a pointer to a function which returns a function pointer, wouldn't you expect the syntax to be more complicated?
You declared foo as a function of the same type as baz, rather than as a pointer to a function of same type as baz.
From your compiler, the first error message is the useful one - it tells you assignment of function, i.e. you have tried to assign to a function, which is an error.
I'm not even going to try to write the correct solution without typedefs :-) Here's some code which compiles and I think is right, using typedefs:
#include <stdlib.h>
#include <stdbool.h>
typedef int(*IntReturnsInt)(int);
int inc(int i) { return i+1; }
IntReturnsInt baz(bool b) { return b ? &abs : &inc; }
int main() {
IntReturnsInt (*foo)(bool b);
foo = baz;
}
In this example the double-function-pointer concept is a bit clearer - IntReturnsInt is a function pointer type and foo is a pointer to a function which returns IntReturnsInt... phew :-)
This is a function declaration.
int (*foo(bool))(int);
If you wanted to declare a function pointer, you should do:
int (*(*foo)(bool))(int);
It's difficult to be sure, but I think this is closer to the OP's intent:
// baz is a function returning a pointer to a function
int (*baz(bool b))(int) { return b ? &abs : &inc; }
int main() {
// foo is a pointer to a function
int (*foo)(int) ;
foo = baz(true); // Now foo is equal to &abs
}
you cannot assign to function type (int (*foo(bool))(int);), you need to use pointer to function
int (*(*foo)(bool))(int);
foo = &baz;
#include <stdlib.h>
#include <stdbool.h>
int inc(int i) { return i+1; } // int→int, like abs()
// baz is bool→(int→int)
int (*baz(bool b))(int) { return b ? &abs : &inc; }
int main() {
int (*(*foo)(bool))(int); // foo is &(bool→(int→int))
foo = baz;
return 0;
}
So there were a few side-issues clouding the core issue. Your "bool" was being interpreted as a default-int untyped parameter because the actual built-in is _Bool, humanized by the previously-missing #include <stdbool.h>. The lack of a pointer declaration for the object on the stack was confounding its ability to conform to the type of the real function object in static memory just above.
Once I included <stdbool.h>, the error shifted to "lvalue required" complaint, because there was only a function declaration and not a pointer object. The code above will compile with no warnings or errors.