explicitly using constructor call in main as a function call parameter - c++

I am trying to understand how explicit constructor call in main works using the following code.
#include<iostream>
using namespace std;
class Dependency1
{
bool init;
public:
Dependency1() : init(true) {
std::cout << "Dependency1 construction"
<< std::endl;
}
void print() const {
std::cout << "Dependency1 init: "
<< init << std::endl;
}
};
class Dependency2 {
Dependency1 d1;
public:
Dependency2(const Dependency1& dep1): d1(dep1){
std::cout << "Dependency2 construction ";
print();
}
void print() const { d1.print(); }
};
void test( const Dependency1& dd1)
{
cout << " inside Test \n";
dd1.print();
}
int main()
{
test(Dependency1());
Dependency2 D1(Dependency1()); // this line does not work
return 0;
}
Function test is being called where constructor Dependency1() is used as a function call instead of Dependency1::Dependency1( ) and the code runs perfectly fine.
Now if I use similar concept to create an object D1 of Dependency2, it does not work.
Seems I am doing something wrong here based on wrong understanding.
Need to know how the Compiler resolves Dependency1() call in main even if scope resolution is not used and why it does not work when I use it as a parameter in constructor of Dependency2
Thanks,
Anand

test(Dependency1())
This calls a function test and passes a temporary object of class Dependency1. Because the formal parameter in the definition of test is a reference to const and because temporaries can be bound to const references your code works.
Dependency2 D1(Dependency1()); // this line does not work
This is called C++ most vexing parse. D1 is interpreted as a function returning Dependency2 and taking an argument a pointer to function returning Dependency1.
Try Dependency2 D1((Dependency1())); and see the change in output.
Note: Putting an extra pair of parenthesis would make the compiler treat (Dependency1()) as an expression.

Dependency1() creates a temporary object of type Dependency1, that is passed to function test.

Related

How do I pass a temporary object as a non-const reference into a member function?

We are creating a class designed to send information out from the current module (the specifics are not relevant to this question). An object of this type is created and populated with a portion of the data that needs to be sent, and then passed into a (different class) member function. That function provides the object with the rest of the data, and then triggers the send, via a call in the object itself. Because the information being passed in is dynamic, the intention is that the information transfer object be a temporary one, created with the latest data. The design we lined out is in the distilled source code below, but gcc/C++ does not allow this, giving the error shown.
The question is, how can we accomplish the intended behavior, using temporary objects (nice for avoiding memory leaks) that can be modified and used by the called function?
gcc compiler error:
infoxfer.cpp: In function ‘int main()’:
infoxfer.cpp:54:43: error: cannot bind non-const lvalue reference of type ‘XferInfo&’ to an rvalue of type ‘XferInfo’
51 | callee.doSomething("Something param", XferInfo("from main()"));
| ^~~~~~~~~~~~~~~~~~~~~~~
infoxfer.cpp:36:62: note: initializing argument 2 of ‘void Callee::doSomething(const string&, XferInfo&)’
33 | void doSomething(const string& somethingParam, XferInfo& xferInfo)
| ~~~~~~~~~~^~~~~~~~
The distilled sample code:
infoxfer.cpp:
#include <iostream>
using std::cout;
using std::endl;
#include <string>
using std::string;
class XferInfo
{
private:
const string mCallerInfo;
string mCalleeInfo;
public:
XferInfo(const string& callerInfo) : mCallerInfo(callerInfo)
{}
void setCalleeInfo(const string& calleeInfo)
{
mCalleeInfo = calleeInfo;
}
void sendData()
{
// simulate sending data
cout << mCallerInfo << " | " << mCalleeInfo << endl;
}
};
class Callee
{
public:
void doSomething(const string& somethingParam, XferInfo& xferInfo)
{
// complete data for xfer
xferInfo.setCalleeInfo(somethingParam);
// simulate doing something
cout << "do something" << endl;
// send the complete info
xferInfo.sendData();
}
};
int main()
{
cout << "start" << endl;
Callee callee;
callee.doSomething("Something param", XferInfo("from main()"));
cout << "end" << endl;
return 0;
}
As mentioned in the comments, you could simply change your doSomething function to accept an rvalue reference to the passed XferInfo object (using the double &&):
void doSomething(const string& somethingParam, XferInfo&& xferInfo)
{
// complete data for xfer
xferInfo.setCalleeInfo(somethingParam);
// ... and so forth ...
From the linked cppreference page:
Rvalue references can be used to extend the lifetimes of temporary
objects (note, lvalue references to const can extend the lifetimes of
temporary objects too, but they are not modifiable through them)

functor: wrapping std::function in a class

Say I am writing a library that should provide some default computing (function), but enables the user to provide his own, at compile-time.
For instance, say the library provides a function that returns his argument times 3, but the user can provide his own function.
Consider the following program (to be seen as a MWE):
float myFunction( float v ) // the function the user needs
{
return v*2;
}
int main()
{
FuncWrapper f;
cout << "default: " << f(2) << endl; // should print "6"
f.AssignFunction( myFunction );
cout << "now is: " << f(2) << endl; // should print "4"
}
So I have build a functor FuncWrapper that wraps a std::function, as proposed also here:
struct FuncWrapper
{
std::function<float(float)> foo; // the function used
float def( float v ) // the default behaviour member function definition
{
return v*3;
}
float operator()( float v ) // call of function
{
return foo(v);
}
void AssignFunction( float (*uf)(float) ) { foo = uf; }
// constructor: initializes to default function
FuncWrapper() : foo(&FuncWrapper::def) {}
};
On my machine (gcc 4.6.3) with -std=c++0x, I get non human-readable error messages, as stated in this other answer. For conveniency, the code is runnable here. Seems to be gcc 4.8, and it doesn't like the constructor (among other errors...):
main.cpp: In constructor 'FuncWrapper::FuncWrapper()':
main.cpp:27:64: error: no matching function for call to 'std::function<float(float)>::function(float (FuncWrapper::*)(float))'
Why is this assignment illegal ? I have searched for this topic, maybe wrong keyword, but didn't find anything relevant.
Any clue? Or a simpler solution, maybe without std::function but with a function pointer?
In your example code, you try to assign your member function to a std::function with signature float(float). These two are not compatible, since the member function has a different calling convention: it requires a this argument.
Make your default function static to avoid this.

Storing rvalue references: should this work?

I'm testing my understanding of lvalue and rvalue references by intentionally trying to break things. So say there is this struct:
struct FooBar
{
FooBar(int&& number) : rNumber(number)
{
}
int& rNumber;
};
and I create an instance FooBar obj(5). Every attempt to read the reference variable returns the right result (5). The same happens if I use const int& instead of int&&.
I noticed that replacing int with std::string and reading the reference returns an empty string, so I suspect it gives undefined behaviour. Is this so? And if so, why does it work with integers?
Update: I'm creating the instance and reading it like this:
FooBar obj(5);
//FooBar obj("Hello"); // For strings...
std::cout << obj.rNumber << std::endl;
Update 2: It also works if you pass a user-defined type, like this:
struct GooBar
{
public:
GooBar(int number) : itsNumber(number)
{
std::cout << "In constructor..." << std::endl;
}
GooBar(const GooBar& rhs) = delete;
GooBar(GooBar&& rhs) = delete;
~GooBar()
{
std::cout << "In destructor..." << std::endl;
}
int itsNumber;
};
struct FooBar
{
FooBar(GooBar&& number) : rNumber(number)
{
}
GooBar& rNumber;
};
and then creating an instance and reading it like so:
FooBar obj(GooBar(5));
std::cout << obj.rNumber.itsNumber << std::endl;
I think this is interesting, because it gives the following output:
In constructor...
In destructor...
5
With an integer literal as actual argument the compiler may pass a reference to a statically allocated instance.
With a std::string formal argument and a string literal as actual argument, the instance is created in the call, and is destroyed at the end of the call.
In both cases it's Undefined Behavior.
It's not clear how you call this though: you forgot to include that crucial information (as the question is as at time I'm writing this).

function not called with the same name as a class

Why the function bellow void i( ) is not called as in a 'Normal' function.
void i(){
cout << 10 << endl;
}
int main(){
class i {
int j;
};
i();//
return 0;
}
The normal behavior expected is to print 1O, but I did not getting anything, not a compiler warning nor the result.
The inner i is shadowing the outer one. You are calling the default constructor of class i which does nothing in this case.
The solution is to explicitly scope the call, as ::i();
Because it's trying to call "i" in the current scope:
You can call your function::i();

copy/conversion constructor definitions (const/non-const)

Let me demonstrate with a simple example:
class A
{
public:
A() { cout << "A::A()" << endl; }
A(A const& a) : _a(a._a) { cout << "A::(A Copy Const)" << endl; }
A(A& a) : _a(a._a) { cout << "A::(A Copy)" << endl; }
template <typename _T1>
A(_T1& v1) : _a(v1) { cout << "A::(T conversion)" << endl; }
~A() { cout << "A::~A()" << endl; }
void say() { cout << "A::say()" << endl; }
private:
int _a;
};
int main(int argc, char* argv[])
{
A a1(A(argc)); // Line 1: ERM?
a1.say();
return 0;
}
Couple of things:
Is there any harm in defining a const and non-const version of the copy constructor? Reason I've done this is that this apparently helps the compiler differentiate from the templated constructor, i.e.
A const a1(argc);
A a2(a1); // <-- correctly call the const copy ctor
A a3(argc);
A a4(a3); // <-- correctly call the non-const copy ctor
Is there a better way to ensure that in the above example, the copy constructor is always called over the templated constructor?
Secondly, from a pure coding perspective, Line 1 appears to be okay, the intention is to create a temporary A with argc, and then trigger the copy constructor, however I get the following exception (gcc 4.4.4):
error: request for member ‘say’ in ‘a1’, which is of non-class type ‘A(A)’
I believe that what's happening here is that the compiler thinks that a1 is a function definition, is this correct? If so, what is the correct way to write that particular line of code? The following appears to be a hack!
A a1(true ? A(argc) : A());
p.s. Please ignore all stylistic foobars and why exactly I want to do this...! :)
A templated constructor is never a (formal) copy constructor.
You're right that a declaration that could be a function declaration is treated as a function declaration. It's called "the most vexing parse" of C++. One workaround is to use extra parentheses, like T v(( U )).
It may be that adding an auto keyword would fix it also, I haven't tried. But since auto gains new meaning in C++0x, it's probably not a good idea to get into habit of using it even if it works for that problem in C++98.
Cheers & hth.