How to invoke non-default constructor for template class? - c++

I have the following code structure (Resource and Parameter are empty classes):
Solver.cpp
#include "Solver.h"
#include "ValueFunction.h"
using namespace std;
template<typename T>
Solver<T>::Solver(vector<vector<Resource> >& resources, const Parameter& params) :
states(resources.size()) {
for (int i=0; i<resources.size(); i++) {
states[i] = State<T>(resources[i], params);
}
}
// Explicit class declaration
template class Solver<ValueFunction>;
Solver.h
#ifndef SOLVER_H_
#define SOLVER_H_
#include <vector>
#include "Resource.h"
#include "Parameter.h"
#include "State.h"
template<typename T>
class Solver {
public:
Solver(
std::vector<std::vector<Resource> >& resources,
const Parameter& params
);
private:
std::vector<State<T> > states;
};
#endif /* SOLVER_H_ */
State.cpp
#include "State.h"
#include "ValueFunction.h"
using namespace std;
template<typename T>
State<T>::State(vector<Resource>& _resources, const Parameter& params) :
resources(_resources), valfuncs(_resources.size(), T(params)) {
}
template class State<ValueFunction>;
State.h
#ifndef STATE_H_
#define STATE_H_
#include <vector>
#include "Parameter.h"
#include "Resource.h"
template<typename T>
class State {
public:
State() {};
State(std::vector<Resource>& _resources, const Parameter& params);
~State() {};
private:
std::vector<Resource> resources;
std::vector<T> valfuncs;
};
#endif /* STATE_H_ */
ValueFunction.cpp
#include "ValueFunction.h"
ValueFunction::ValueFunction(const Parameter& _params) : params(_params) {
}
ValueFunction.h
#ifndef VALUEFUNCTION_H_
#define VALUEFUNCTION_H_
#include "Parameter.h"
class ValueFunction {
public:
ValueFunction(const Parameter& _params);
private:
const Parameter& params;
};
#endif /* VALUEFUNCTION_H_ */
With the following call:
#include "Solver.h"
#include "State.h"
#include "ValueFunction.h"
#include "Parameter.h"
using namespace std;
int main(int argc, char *argv[]) {
Parameter params;
vector<vector<Resource> > resources(4);
Solver<ValueFunction> sol(resources, params);
return 0;
}
And I get the following error:
Solver.cpp:18:16: instantiated from here
ValueFunction.h:6:21: error: non-static reference member ‘const Parameter& ValueFunction::params’, can't use default assignment operator
How can I invoke the non-default constructor for ValueFunction correctly, or is there an other way to initialize an std::vector with a non-default constructor (passing a constant reference)?
Update
The error is explained in this post. But the workaround for my problem is not entirly clear. Any suggestions?

You are initializing the states of Solver using the form of the constructor that calls the default constructor of the vector members. You can pass in a second parameter to the vector constructor for states of type State<T>, and the vector will use the copy constructor to initialize the vector elements using that parameter as the source. Your loop in the Solver constructor will still work to provide the values you actually want within the states vector.
A reference cannot be initialized by the compiler generated default constructor. This is because it is the job of the default constructor to initialize the object, but a reference needs something to refer to. Just as you get an error declaring a reference variable with no initializer, the default constructor encounters the same problem.
int &r; // this is an error
int i;
int &rr = i; // this is proper
Using the copy constructor version of the vector constructor helps you to avoid the problem, because the copy constructor initializes the reference with the value of the object it is copying. In this form of initializing a vector, each of the elements in states gets set to the same value as the first element.
...
: states(resources.size(), State<T>(resources[0], params))
...
Perhaps the better way to go is to use the default constructor for the vector itself, and use reserve and push_back to add elements to the vector. This is better because it avoids creating any State<T> objects at all until it is actually added to the vector.
...
: states()
...
states.reserve(resources.size());
for (int i...) {
states.push_back(State<T>(resources[i], params));
}
...
A third approach that would sort of allow your original code to work the way it was written is to define your own default constructor for ValueFunction that initializes the params member to something (perhaps the dreaded global).
class ValueFunction {
public:
ValueFunction (); // define our own default constructor
...
};
const Parameter global_default_parameter;
ValueFunction::ValueFunction () : params(default_parameter) {}

Related

How to implement constructors of Class A that has a member variable vector <Class B>,which is its Base function, using initializer_list and template?

So the problems are:
Class Stan must have a constructor that enables it to recieve and store unlimited nubmer of elements and it has to be implemented using templates. Also, demonstrate it in the main function
Class Stan must have a constructor that enables it to recieve and store unlimited nubmer of elements and it has to be implemented using initializer lists. Also, demonstrate in main function
Place class Stan into the namespace Zgrada
Lets assume that there are 2 types of Stans - Apa & Gar. Within the main function it is necessary to demonstrate polimorphism by implementing getVrsta(); which returns one of the 2 types
I have no clue how to do more than this.
Thanks for the help!
#include <string>
#include <vector>
#include <functional>
#include <algorithm>
#include <iterator>
using namespace std;
int Element::brV = 0;
class Element {
public:
string naziv;
double obujam;
static int brV;
Element(string n, double o) : naziv(n), obujam(o) {
if (o > 3.) brV++;
}
int getVelikiElementi(){
return brV;
}
void virtual GetVrsta(){
cout << "Vrsta Stana: ";
}
};
template <class T> //I think i got the templates_init right
class Stan : public Element {
public:
vector<Element> Elementi;
template<class...T>
Stan(T...arg) : Elementi({arg...}){}
Stan(initializer_list<Elementi>) : Element (){} // But this most certainly not
void GetVrsta(){
}
};
int main () {
Element X("a", 3.);
Element Y("b", 2.);
Element Z("c", 1.);
vector <Element*> E={X,Y,Z}; // initilizer_lista_const_call
return 0;
}```

invalid pointer when using strings for generic class

So this is for my data structures class and I am struggling to understand why I am getting the error: invalid pointer: 0x00000000023ce048 ***. It only happens when I define my generic class using strings: NSequence<string> v3(10);
It should be noted that using int or even a different class worked fine. However, as soon as I write the line: NSequence<string> v3(10); I get the pointer error and I have no idea why?
UPDATE:
I've found that it was actually my destructor class that was causing the error. However, I now have no idea why this would cause an error specifically with string?
template<typename T>
NSequence<T>::~NSequence()
{
delete items;
}
Here is the definition of my class:
#include <algorithm>
#include <iostream>
#include <utility>
/* XXX: Implement all member functions for NSequence in NSequence.hpp */
template <typename T>
class NSequence
{
public:
explicit NSequence( int initSize = 0 );
private:
int numOfItems;
int totalCapacity;
T * items;
};
#include "NSequence.hpp" // do not change this line
#endif
Here is my constructor function:
template<typename T>
NSequence<T>::NSequence(int initSize)
{
if(initSize==0)
initSize=1;
numOfItems = initSize;
totalCapacity = initSize;
items = new T[totalCapacity];
}
Any advice would be greatly appreciated!

Why Do I get this error on vector initialisation?

I have a problem with vector declaration and initialization in a
class constructor. I have a Station.h and Station.cpp files of a class and I recall it in main :
Station.h
#ifndef STATION_H
#define STATION_H
#include <vector>
class Station
{
public:
int num_bin;
int num_staz;
vector<int> binari; //here already gives me error! Vector does not name a type
Station(int num_staz, int num_bin);
virtual ~Station();
Station(const Station& other);
protected:
private:
};
Then I want to initialize the vector in the constructor of .cpp like that:
Station.cpp
#include "Station.h"
using namespace std;
Station::Station(int num_staz, int num_bin)
{
this->num_bin = num_bin;
this->num_staz = num_staz;
this->binari(num_bin); //here I want to create a vector of num_bin size
}
and then call it in main like that:
main.cpp
#include <iostream>
#include "Station.h"
using namespace std;
int main()
{
Station staz1(2,3);
staz1.binari.push_back(300); // error! class Station has no member binari
staz1.binari.push_back(250);
staz1.binari.push_back(150);
return 0;
}
Where am I making a mistake?
this->binari(num_bin); //here I want to create a vector of num_bin size
The function you need to use is std::vector::resize().
this->binari.resize(num_bin);
It will be better to initialize the object with the appropriate size as:
Station::Station(int num_staz, int num_bin) : num_bin(num_bin),
num_staz(num_staz),
binari(num_bin)
{
}
this->binari(num_bin); This doesn't work because it is not an initialization that is why it doesn't work.
To make this work use it in in-class initialization list:
Station::Station(int num_staz, int num_bin) :
num_bin(num_bin),
num_staz(num_staz),
binari(num_bin)
{
}

No Default constructor to run functions in c++?

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.

error: expected constructor, destructor, or type conversion before '(' token

include/TestBullet.h:12: error: expected constructor, destructor, or type conver
sion before '(' token
I hate C++ error messages... lol ^^
Basically, I'm following what was written in this post to try to create a factory class for bullets so they can be instantiated from a string, which will be parsed from an xml file, because I don't want to have a function with a switch for all of the classes because that looks ugly.
Here is my TestBullet.h:
#pragma once
#include "Bullet.h"
#include "BulletFactory.h"
class TestBullet : public Bullet {
public:
void init(BulletData& bulletData);
void update();
};
REGISTER_BULLET(TestBullet); <-- line 12
And my BulletFactory.h:
#pragma once
#include <string>
#include <map>
#include "Bullet.h"
#define REGISTER_BULLET(NAME) BulletFactory::reg<NAME>(#NAME)
#define REGISTER_BULLET_ALT(NAME, CLASS) BulletFactory::reg<CLASS>(NAME)
template<typename T> Bullet * create() { return new T; }
struct BulletFactory {
typedef std::map<std::string, Bullet*(*)()> bulletMapType;
static bulletMapType map;
static Bullet * createInstance(char* s) {
std::string str(s);
bulletMapType::iterator it = map.find(str);
if(it == map.end())
return 0;
return it->second();
}
template<typename T>
static void reg(std::string& s) {
map.insert(std::make_pair(s, &create<T>));
}
};
Thanks in advance.
And unrelated to the error, but is there a way to let Bullet include BulletFactory without creating tons of errors (because of circular inclusion)? This way I would be able to remove #include "BulletFactory.h" from the top of all of the bullet subclasses.
I don't think you can call functions outside of functions (as long as you don't use the result to initialize a global).
Here's how you get what you want. (Not using your code, exactly, skips including headers, etc. Just for the idea.):
// bullet_registry.hpp
class bullet;
struct bullet_registry
{
typedef bullet* (*bullet_factory)(void);
std::map<std::string, bullet_factory> mFactories;
};
bullet_registry& get_global_registry(void);
template <typename T>
struct register_bullet
{
register_bullet(const std::string& pName)
{
get_global_registry().mFactories.insert(std::make_pair(pName, create));
}
static bullet* create(void)
{
return new T();
}
};
#define REGISTER_BULLET(x) \
namespace \
{ \
register_bullet _bullet_register_##x(#x); \
}
// bullet_registry.cpp
bullet_registry& get_global_registry(void)
{
// as long as this function is used to get
// a global instance of the registry, it's
// safe to use during static initialization
static bullet_registry result;
return result; // simple global variable with lazy initialization
}
// bullet.hpp
struct my_bullet : bullet { };
// bullet.cpp
REGISTER_BULLET(my_bullet)
This works by making a global variable, which will be initialized at some point during static initialization. When that happens, in its constructor it accesses the global registry and registers it with the name, and the function used to create bullets.
Since static initialization order is unspecified, we put the global manager in a function, so when that function is called the first time the manager is created on-demand and used. This prevents us from using an uninitialized manager, which could be the case if it were a simple global object.
Free free to ask for clarifications.
reg() is a function. You can't call a function without a scope.