Argument constructor call invocation - c++

I am a bit puzzled about this. When default stack allocated object construction is allowed as member varaiable of other struct, why not parameterized construction ? Does Most Vexing Parse has anything to do with this ? I tried on C++0X as well at ideone and got the same result.
struct foo{
foo() {}
foo(int i) {}
};
struct bar{
foo obj; // Allowed
foo obj2(10); // Not Allowed
};
Error: expected ‘,’ or ‘...’ before numeric constant
IdeOne Demo

Your link to Most Vexing Parse discusses instantiation of non-member variables (variables which are not a member of a class/struct). The example you've shown is that of member variables being declared in a struct; for which you would typically initialise them in a constructor
struct bar
{
foo obj;
foo obj2;
bar() : obj2(10) {}
};
The Most Vexing Parse problem occurs in situations such as the below:
struct baz
{
baz(int n) {}
};
void foo()
{
baz meow(int());
}
where the identifier meow appears to be a function declaration of type baz (int), due to the 'most vexing parse' issues described in your link. (the int() which at first glance appears to be default-initialisation actually turns out to be simply the data type int)

write
struct bar {
foo obj;
foo obj2;
foo(): obj2(10) {}
}
This way, when instantiating bar, obj2 construction will be made with 10.

Prior to C++11, you couldn't initialize members in the declaration unless they were static const and integral.
In C++11, you can use uniform initialization and in-class member initializtion:
foo obj2{10};
Since the constructor is not explicit, you can also do this:
foo obj2 = 10;
Not in C++11, you have to use a member initializer in the constructor list.

Related

Defer calling constructor of member object declared in header until source file

I'd like to do declare a member object within the class declaration within my header file. I want to defer the calling of the member's constructor until the corresponding source file.
This is ideally what I'd like, just for illustration:
// foo.h
class Bar(string First, string Second);
class Foo : public Base {
public:
Foo(int a);
Bar b; // I don't want to construct here!
...
// foo.cc
Foo::Foo(int a)
: base(a)
, b("first", "second") // <-- construct here
{}
edit: The code above is calling the "default constructor" for Bar. I get:
error: could not convert ‘{arg}’ from ‘<brace-enclosed initializer list>’ to ‘Bar’
Bar bar;
Changing the type of b to a pointer will ripple through too many things.
Changing it to a REFERENCE is probably tenable. In the code below, since no constructor is called in the header file, that's okay for my needs!
// foo.h
class Bar;
class Foo : public Base {
public:
Foo(int a);
Bar& b; // now it's a non-constant reference, but unassigned
...
// foo.cc
Foo::Foo(int a)
: base(a)
, b{"first", "second"} // <-- construct here
{}
However, this results in the error: non-const lvalue reference to type 'Bar' cannot bind to an initializer list temporary. That makes sense too.
I guess I'm asking how would you do this? Is something like std::reference_wrapper going to be useful?
C++11 is a restriction.
The constructor of a member object is called from all constructors of the containing class. That includes compiler-generated constructors.
Hence, you need to make sure that the definitions of all these constructors are in foo.cc. Now you only show Foo::Foo(int), but that's not the constructor which is causing the problem.
I can and do include the full definition
It's exceedingly difficult to get a straight response to you so I'll go with that quote specifically and assume you meant you have a fully defined Bar type before your Foo definition.
If that's the case, your first part of the code does work as intended (once you fix the weird syntax and semantic and every other kind of errors, of course). Specifically, this works as expected:
#include <string>
using namespace std;
struct X {
X(string a, string b) {}
};
struct Y {
X x;
Y() : x("a", "b") {}
};

Initialization of std::array with function pointer member function of constexpr object

I am trying to initialize an std::array of function pointers. These pointers point to member functions of an already instantiated object.
Can somebody please help with the following example? Many thanks in advance!
#include <array>
using TVoidVoid = void (*)(void);
class Foo {
public:
constexpr Foo() {}
void myHandler() {}
};
class Bar {
public:
constexpr Bar() : handler_{nullptr} {}
constexpr Bar(TVoidVoid handler) : handler_{handler} {}
private:
TVoidVoid handler_;
};
Foo f;
std::array<Bar, 5> bar_array = {{Bar{}, Bar{f.myHandler}}};
int main() {}
compiling produces:
main.cpp:22:56: error: no matching function for call to ‘Bar::Bar(<brace-enclosed initializer list>)’
std::array<Bar, 5> bar_array = {{Bar{}, Bar{f.myHandler}}};
I am using g++ (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0.
Pointers to free functions are handled differently than pointers to member functions. The TVoidVoid type is a pointer to a free function, but you need a pointer to a Foo member function. Hence, define Foo first,
class Foo { /* As before... */ };
then go with a type alias for the member function (Foo must be known at this point)
// Note the different syntax to the former TVoidVoid
using FooVoidVoid = void (Foo::*)();
Next, Bar must be adjusted such that its data member is of type FooVoidVoid and the constructor accepts this type as an argument (the rest of Bar can be left as it is), and finally defined the array as
std::array<Bar, 3> bar_array = {{Bar{}, Bar{&Foo::myHandler}}};
Note that &Foo::myHandler has nothing to do with any existing Foo instance. It's just a pointer to a Foo member function, and only when you invoke it, this must be brought together with a Foo object (the special operators .* and ->* are meant for this to happen, or use std::invoke once you upgrade to a C++17-enabled compiler).

All versions of GCC struggle with default member initializer, that captures this, combined with inherited constructors

This story is similar to my previous question. All versions of GCC that support C++11, have this exact behaviour. I could not find any other compiler that struggles with my test case.
The test case:
struct BaseFooWrapper
{
BaseFooWrapper(int qux)
{ }
};
struct Foo
{
Foo(BaseFooWrapper & foo)
: foo(foo)
{ }
BaseFooWrapper & foo;
};
struct SomeFooWrapper : public BaseFooWrapper
{
using BaseFooWrapper::BaseFooWrapper;
Foo foo{*this};
};
int main()
{
SomeFooWrapper wrapped_foo(1);
return 0;
}
Live on godbolt.com
This piece of code compiles with clang (3.4 through 4.0), icc (16, 17), Visual C++ (19.00.23506).
If I replace constructor inheritance with a hand-written version, then GCC starts to compile the code:
struct BaseFooWrapper
{
BaseFooWrapper(int qux)
{ }
};
struct Foo
{
Foo(BaseFooWrapper & foo)
: foo(foo)
{ }
BaseFooWrapper & foo;
};
struct SomeFooWrapper : public BaseFooWrapper
{
SomeFooWrapper(int qux)
: BaseFooWrapper(qux)
{ }
Foo foo{*this};
};
int main()
{
SomeFooWrapper wrapped_foo(1);
return 0;
}
Live on godbolt.com
Obviously it is not very handy, especially when you have many such classes, and leads to boilerplate code. Basically, the very thing that inheriting constructors are designed to fix. This behaviour of GCC renders this great c++11 feature unavailable in such cases.
So I am really curious whether I am doing something illegal with regard to the standard or this is a bug in GCC?
Edit:
Filed a bug report.
The problem is not the constructor inheritance, but this line:
Foo foo{*this};
GCC appears to think it will need a default constructor for struct Foo as well, and since the class has a reference, it is not able to do so.
error: no matching function for call to 'Foo::Foo()'
<source>:14:5: note: candidate: Foo::Foo(BaseFooWrapper&)
Foo(BaseFooWrapper & foo): foo(foo)
^~~
<source>:14:5: note: candidate expects 1 argument, 0 provided
<source>:10:7: note: candidate: constexpr Foo::Foo(const Foo&)
By adding the default constructor it appears to think it needs, then the code compiles:
struct Foo
{
Foo():foo(*new BaseFooWrapper(0))
{
}
Foo(BaseFooWrapper & foo): foo(foo)
{
}
BaseFooWrapper & foo;
};
It does look like a bug.
I could be wrong, but quoting from the n4527 draft standard in [class.this]:
In the body of a non-static (9.3) member function, the keyword this is a prvalue expression whose value
is the address of the object for which the function is called. The type of this in a member function of
a class X is X*.
In the OP's code, the initialisation of SomeFooWrapper::foo is not taking place in a member function. Therefore the keyword this has no reasonable meaning as far as the standard is concerned.
Or have I missed something?

deleted default constructor headache

My c++ book says this (lippman, c++ primer, fifth ed., p. 508):
The synthesized default constructor is defined as deleted if the class ... has a const member whose type does not explicitly define a default constructor and that member does not have an in-class initializer. (emphesis mine)
Why then does this code produce an error?
class Foo {
Foo() { }
};
class Bar {
private:
const Foo foo;
};
int main() {
Bar f; //error: call to implicitly-deleted default constructor of 'Bar'
return 0;
}
The rule above seems to indicate that it should not be an error, because Foo does explicitly define a default constructor. Any ideas?
To fix your error. You need to make Foo::Foo() public.
class Foo
{
public:
Foo() { }
};
Otherwise I do believe it is private.
Is this what your looking for?
The default constructor is omitted when a a class construction isn't trivial.
That in general means that either there is an explicit constructor that receives parameters (and then you can't assume that it can be constructed without those parameters)
Or if one of the members or base classes need to be initiated in construction (They themselves don't have a trivial constructor)
I think that this should work
class Foo {
public:
Foo() { }
};
class Bar {
public:
Bar() : foo() {}
private:
const Foo foo;
};

Use of this in initializer list

Suppose I have a class Baz that inherits from classes Foo and Bar, in that order. The constructor for class Bar takes a pointer to a Foo object. What I would like to do is to pass this as the Foo object to the Bar constructor:
Baz () : Foo(), Bar(this) {}
A working example:
#include <iostream>
class Bar;
class Foo {
public:
virtual ~Foo() {}
virtual void parse_bar (Bar&) const = 0;
};
class Bar {
private:
const Foo * parser;
public:
Bar (const Foo * parser_in) : parser(parser_in) {}
virtual ~Bar() {}
void parse_self () { parser->parse_bar (*this); }
};
class Baz : public Foo, public Bar {
public:
Baz () : Foo(), Bar(this) {}
virtual void parse_bar (Bar &) const { std::cout << "Hello World\n"; }
};
int main () {
Baz baz;
baz.parse_self();
}
This happens to work on my computer, with my compilers (tested with a couple of them). However section 9.3.2 of the 2003 standard makes me a bit uneasy that I might just be getting lucky, that using this this way is undefined behavior. Strictly speaking, the initializer list is outside the body of the constructor. Here's the relevant text, emphasis mine:
9.3.2 The this pointer
In the body of a nonstatic member function, the keyword this is a non-lvalue expression whose value is the address of the object for which the function is called.
So is my usage legal and well-defined, or is it undefined behavior?
There are two points that have to be noted in this case.
Firstly, in the constructor initializer list this pointer refers to a non-constructed (or not-fully-constructed) object. It is OK to access such pointer, but the object it refers to can only be used in limited ways. See 12.7 in the language specification.
Secondly, in your specific example what you are actually doing is converting this pointer to Foo * type before attempting any access. This is completely safe since by that moment the Foo subobject is fully constructed. (I assume that, whatever access will follow, if any, will be restricted only to the fully constructed Foo subobject).
The only concern is this case is whether it is legal to convert this to Foo * type, i.e. whether the conversion process itself should succeed. The answer is: yes, in case of ordinary (non-virtual) inheritance such conversion is perfectly legal and safe (again, explicitly allowed in 12.7)
It is fine. The C++ standard actually clarifies the use of this pointers in initializer lists:
12.6.2 Initializing bases and members [class.base.init]
Paragraph 7: Names in the expression-list of a mem-initializer are evaluated in the scope of the constructor for which the mem-initializer is specified. [Example:
class X {
int a;
int b;
int i;
int j;
public:
const int& r;
X(int i): r(a), b(i), i(i), j(this->i) {}
};
initializes X::r to refer to X::a, initializes X::b with the
value of the constructor parameter i, initializes X::i with the
value of the constructor parameter i, and initializes X::j with
the value of X::i; this takes place each time an object of class X
is created. ] [Note: because the mem-initializer are evaluated in
the scope of the constructor, the this pointer can be used in the
expression-list of a mem-initializer to refer to the object being
initialized. ]
The type of the this pointer in the initializer of Baz is in fact of type Baz. Of course, you have to be mindful of the fact that not all of the members may have been initialized. Many, if not all, compilers set at their highest warning levels (which you really should be doing anyway) will warn about you passing a this pointer to the base class.
However, it looks like you're making it more complicated that it needs to be. Why not just put the virtual function parse_bar() in the Bar class, and forget about the Foo class?
#include <iostream>
class Bar
{
public:
Bar() {}
virtual ~Bar() {}
void parse_self () { parse_bar(); }
private: // Template method pattern
virtual void parse_bar() const = 0;
};
class Baz : public Bar
{
public:
Baz () {}
private: // Yes, this does override the private `parse_bar()` member!
virtual void parse_bar() const { std::cout << "Hello World\n"; }
};
int main ()
{
Baz baz;
baz.parse_self();
}
This does essentially the same function but with less code.