I am trying to make a class with two constructors. One that is a default constructor, the other calling the parameterized constructor. I get a compiler error that tells me that I cannot use move on the object just created and I sort of understand that it doesn't like to do that, because there is no real assignment here.
How can I achieve the right behavior? I am trying to avoid writing two constructors that initialize the variables. An initialization function might work, but then I would have to fill the body of the constructors and I was trying to come up with a neat solution like shown below.
#include <string>
#include <iostream>
#include <memory>
using namespace std;
class Foo
{
public:
Foo(unique_ptr<int>& number) : m_number(move(number))
{
}
Foo() : Foo(make_unique<int>(54))
{
}
void print()
{
cout << m_number << endl;
}
private:
unique_ptr<int> m_number;
};
int main()
{
Foo f;
f.print();
return 0;
}
main.cpp:18:33: error: invalid initialization of non-const reference
of type ‘std::unique_ptr&’ from an rvalue of type
‘std::_MakeUniq::__single_object {aka std::unique_ptr}’
Foo() : Foo(make_unique(54))
I decided to go for an rvalue constructor. This seems to resolve the issue for me.
#include <string>
#include <iostream>
#include <memory>
using namespace std;
class Foo
{
public:
// rvalue constructor so that we can move the unique_ptr.
Foo(unique_ptr<int>&& number) : m_number(move(number))
{
}
Foo() : Foo(make_unique<int>(54))
{
}
void print()
{
cout << *m_number << endl;
}
private:
unique_ptr<int> m_number;
};
int main()
{
Foo f;
f.print();
unique_ptr<int> a = make_unique<int>(33);
Foo f2(move(a)); // important to do a move here, because we need an rvalue.
f2.print();
return 0;
}
Related
I have a bit of trouble understanding a std::bind call.
In the following example:
#include <functional>
#include <iostream>
#include <memory>
class Notifier
{
public:
Notifier(std::function<void(Notifier&)> on_notify)
:on_notify_(on_notify)
{ }
void notify()
{
if (on_notify_)
on_notify_(*this);
}
std::function<void(Notifier&)> on_notify_;
};
struct Manager
{
Manager()
{
n_ = std::make_unique<Notifier>(std::bind(&Manager::trigger, this));
}
void trigger()
{
std::cout << "notified" << std::endl;
}
std::unique_ptr<Notifier> n_;
};
int main()
{
Manager s;
s.n_->notify();
}
I don't understand how on_notify_(*this); calls back the functor with a Notifier& parameter, but the functor created by bind doesn't specify it.
The calls result correctly to the void notify() method, but I don't understand what exactly will be the functor created by bind to result in this.
If I were to write a lambda instead, I would need to specify the parameter, otherwise it would compile.
What kind of operation does bind here behind my back? :-)
std::bind basically ignores the invalid given argument according to this.
If some of the arguments that are supplied in the call to g() are not matched by any placeholders stored in g, the unused arguments are evaluated and discarded.
It might surprise you that when even more absurd arguments are provided, the binded functor can still successfully reach Manager::trigger() as follows:
#include <functional>
#include <iostream>
#include <memory>
// Some classes that have nothing to do with on_notify_
class AAA {};
class BBB {};
class Notifier
{
public:
Notifier(std::function<void(AAA&, BBB&)> on_notify)
:on_notify_(on_notify)
{ }
void notify()
{
if (on_notify_)
{
// Arguments not matching.
AAA a{};
BBB b{};
// Invoke with them.
on_notify_(a, b);
}
}
std::function<void(AAA&, BBB&)> on_notify_;
};
struct Manager
{
Manager()
{
n_ = std::make_unique<Notifier>(std::bind(&Manager::trigger, this));
}
void trigger()
{
std::cout << "it's also notified!" << std::endl;
}
std::unique_ptr<Notifier> n_;
};
int main()
{
Manager s;
s.n_->notify();
}
Live demo is here.
I have been playing around with function pointers in c++ and seem to have found a bit of a problem. I made a demo to reproduce the error in a simple example.
I have the header file
class MyClass
{
public:
void MyFunction(int i);
MyClass();
~MyClass();
};
and the cpp file
#include "MyClass.h"
#include <iostream>
#include <functional>
using namespace std;
MyClass::MyClass()
{
//doesn't work
function<void(int)> func = &MyClass::MyFunction;
}
void MyClass::MyFunction(int i)
{
cout << i << endl;
}
In the constructor of the cpp file I am trying to create a pointer to MyFunction. It gives the error error C2664: 'void std::_Func_class<_Ret,int>::_Set(std::_Func_base<_Ret,int> *)' : cannot convert argument 1 from '_Myimpl *' to 'std::_Func_base<_Ret,int> *' in the functional file at line 506. It works fine with a parameterless method, but not with them. Does anyone know why, and how to resolve it?
You can use this and bind the object being constructed to the function. For instance, if your constructor looked like this:
MyClass::MyClass()
{
function<void(int)> func = bind(&MyClass::MyFunction, this, placeholders::_1);
func(6);
}
And you created a MyClass instance:
MyClass instance;
Then 6 will be printed to stdout.
You can also use std::mem_fn in C++11, which wraps a member function/variable into a callable closure
#include <iostream>
#include <functional>
class MyClass
{
public:
MyClass()
{
auto func = std::mem_fn(&MyClass::MyFunction);
func(this, 42); // call it on the current instance
}
void MyFunction(int i)
{
std::cout << i << std::endl;
}
};
int main()
{
MyClass foo;
}
or, you can explicitly specify the instance you're calling the pointer to member function
MyClass()
{
auto func = &MyClass::MyFunction;
(this->*func)(42); // call it on the current instance
}
In particular, note that std::function<void(int)> is not convertible to a pointer to member function. See related Using generic std::function objects with member functions in one class
That's why using auto with std::mem_fn gets rid of all the pain.
i want to run the function Run in the main, but am not allowed to create object due to no default constructor. when i try to create the default constructor, i receive the message, 'Error"Game::Game int maxComponents)" provides no initialiser for:'
//Game.h
#pragma once
#include "GameComponent.h"
#include <time.h>
class Game
{
private:
int componentCount;
GameComponent** components;
const int TICKS_1000MS;
public:
Game(){} //this does not work either
Game(int maxComponents){} //this does not work as my default constructor
~Game();
void Add(GameComponent*);
void Run();
};
//Game.cpp
#pragma once
#include "StdAfx.h"
#include "Game.h"
#include <iostream>
#include<time.h>
using namespace std;
void Game::Add(GameComponent*)
{
components= new GameComponent*[componentCount];
}
void Game::Run()
{
time_t rawtime;
struct tm * timeinfo;
time ( &rawtime );
timeinfo = localtime ( &rawtime );
//cout << timeinfo->tm_hour<< ":" << timeinfo->tm_min << ":" << timeinfo->tm_sec << endl;
for(int n=0;n<componentCount;n++)
{
components[n]->Update(timeinfo);
}
}
Game::~Game()
{
}
//main.cpp
#include "stdafx.h"
#include <iostream>
#include "Game.h"
#include <time.h>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
Game obj1;
obj1.Run();
system("pause");
return 0;
}
So, how do i create a default constructor here? i've tried to use member initialising too, doesn't work. and copy constructor.
A default constructor is a constructor that takes no arguments. So, you should declare a constructor that looks something like this:
Game() { }
You can keep your other constructor - normal function overloading applies to constructors, so it will use your Game(int) constructor when you specify a single integer argument, and Game() when you specify no arguments.
However, in your case Game contains a const int member (TICKS_1000MS). Since it's const, it's expected to be initialized in the constructor. So you should do something like this:
Game() : TICKS_1000MS(123) { } // replace 123 with whatever the value should be
You need to do that for all constructors.
It's a little silly to have a non-static const member of a class which is always initialized to the same value (as opposed to a value passed in as an argument to the constructor). Consider making it an enum instead:
enum { TICKS_1000MS = 123 };
or, a static const member:
static const int TICKS_1000MS;
and initialize it in Game.cpp:
const int Game::TICKS_1000MS = 123;
As long as you have defined a constructor other than than the default one, the default constructor is not provided anymore so you have to define it manually:
public:
Game() {}
Game(int maxComponents){}
Now you have a default constructor and an overloaded constructor which takes 1 integer parameter.
You will need to create the default parameterless constructor. When you define a constructor you no longer get the default that would have been created behind the scenes.
Game(){}
The default constructor is the one that does not take any parameters, in your case Game(){}.
You do not seem to use the constructor parameter, but if you do, you will have to provide a default value.
Probably you can so something along these lines, you class Game needs to initialize const int in both the constructors:
class Game
{
private:
int componentCount;
GameComponent** components;
const int TICKS_1000MS;
public:
Game(): TICKS_1000MS(100)
{} //this does not work either
Game(int maxComponents): TICKS_1000MS(100)
{} //this does not work as my default constructor
~Game();
void Add(GameComponent*);
void Run();
};
As pointed out by others you need to intialize const data in ctor or initializer list.
#include <iostream>
using namespace std;
class B
{
public:
int getMsg(int i)
{
return i + 1;
}
};
class A
{
B b;
public:
void run()
{
taunt(b.getMsg);
}
void taunt(int (*msg)(int))
{
cout << (*msg)(1) << endl;
}
};
int main()
{
A a;
a.run();
}
The above code has a class B inside a class A, and class A has a method taunt that takes a function as an argument. class B's getMsg is passed into taunt...The above code generated the following error message: "error: no matching function for call to 'A::taunt()'"
What's causing the error message in the above code? Am I missing something?
Update:
#include <iostream>
using namespace std;
class B
{
public:
int getMsg(int i)
{
return i + 1;
}
};
class A
{
B b;
public:
void run()
{
taunt(b.getMsg);
}
void taunt(int (B::*msg)(int))
{
cout << (*msg)(1) << endl;
}
};
int main()
{
A a;
a.run();
}
t.cpp: In member function 'void A::run()':
Line 19: error: no matching function for call to 'A::taunt()'
compilation terminated due to -Wfatal-errors.
I'm still getting the same error after changing (*msg)(int) to (B::*msg)(int)
b.getMsg is not the correct way to form a pointer to member, you need &B::getMsg.
(*msg)(1) is not the correct way to call a function through a pointer to member you need to specify an object to call the function on, e.g. (using a temporary) (B().*msg)(1).
The right way to do such things in OOP is to use interfaces so all you need to do is to define an interface and implement it in B class after that pass the pointer of instance which implements this interface to your method in class A.
class IB{
public:
virtual void doSomething()=0;
};
class B: public IB{
public:
virtual void doSomething(){...}
};
class A{
public:
void doSomethingWithB(IB* b){b->doSomething();}
};
This works in VS 2010. The output is the same on all lines:
#include <iostream>
#include <memory>
#include <functional>
using namespace std;
using namespace std::placeholders;
class A
{
public:
int foo(int a, float b)
{
return int(a*b);
}
};
int main(int argc, char* argv[])
{
A temp;
int x = 5;
float y = 3.5;
auto a = std::mem_fn(&A::foo);
cout << a(&temp, x, y) << endl;
auto b = std::bind(a, &temp, x, y);
cout << b() << endl;
auto c = std::bind(std::mem_fn(&A::foo), &temp, _1, y);
cout << c(5) << endl;
}
Basically, you use std::mem_fn to get your callable object for the member function, and then std::bind if you want to bind additional parameters, including the object pointer itself. I'm pretty sure there's a way to use std::ref to encapsulate a reference to the object too if you'd prefer that. I also included the _1 forwarding marker just for another way to specify some parameters in the bind, but not others. You could even specify everything BUT the class instance if you wanted the same parameters to everything but have it work on different objects. Up to you.
If you'd rather use boost::bind it recognizes member functions and you can just put it all on one line a bit to be a bit shorter: auto e = boost::bind(&A::foo, &temp, x, y) but obviously it's not much more to use completely std C++11 calls either.
I'm attempting to create a list of objects using the variant boost.
#include <string>
#include <list>
#include <iostream>
#include <boost/variant.hpp>
using namespace std;
using namespace boost;
class CSquare;
class CRectangle {
public:
CRectangle();
};
class CSquare {
public:
CSquare();
};
int main()
{ typedef variant<CRectangle,CSquare, bool, int, string> object;
list<object> List;
List.push_back("Hello World!");
List.push_back(7);
List.push_back(true);
List.push_back(new CSquare());
List.push_back(new CRectangle ());
cout << "List Size is: " << List.size() << endl;
return 0;
}
Unfortunately, the following error is produced:
/tmp/ccxKh9lz.o: In function `main':
testing.C:(.text+0x170): undefined reference to `CSquare::CSquare()'
testing.C:(.text+0x203): undefined reference to `CRectangle::CRectangle()'
collect2: ld returned 1 exit status
I realise that everything would be fine if i used the form:
CSquare x;
CRectangle y;
List.push_back("Hello World!");
List.push_back(7);
List.push_back(true);
List.push_back(x);
List.push_back(y);
But i would like to avoid that form if at all possible, since i would like to keep my objects unnamed. This is an important requirement for my system - is there any way i can avoid using named objects?
Just need to change a few things and it works:
#include <iostream>
#include <list>
#include <string>
#include <boost/variant.hpp>
using namespace std;
using namespace boost;
class CRectangle
{
public:
CRectangle() {}
};
class CSquare
{
public:
CSquare() {}
};
int main()
{
typedef variant<CRectangle, CSquare, bool, int, string> object;
list<object> List;
List.push_back(string("Hello World!"));
List.push_back(7);
List.push_back(true);
List.push_back(CSquare());
List.push_back(CRectangle());
cout << "List Size is: " << List.size() << endl;
return 0;
}
Specifically, you needed to define the CRectangle and CSquare constructors (that's why you were getting a linker error) and to use CSquare() rather than new CSquare() etc. Also, "Hello World!" has type const char *, so you need to write string("Hello World!") when passing it to push_back or it will get implicitly converted to bool here (not what you want).
Instead of List.push_back(new CSquare()); just write
List.push_back(CSquare());
And also write defination of your constructor
You forget to implement the constructors CRectangle::CRectangle() and CSquare::CSquare().
Either implement them somewhere outside the class such as:
CRectangle::CRectangle()
{
// :::
};
... or implement them inside the class:
class CRectangle {
public:
CRectangle()
{
// :::
}
};
... or remove the constructor declarations altogether:
class CRectangle {
public:
};