In this thread link, concerns the discussion on real example of using the strategy design pattern. The second answer which shows an example of dynamically inserting rules to whether approve/decline the assignment of products to people with the RuleAgent. This set of rules is invoked using the function IsApproved.
The example shows what if we wanted to add two more rules, like an intern rule and overtime rule. My question relates to how do we ensure that our polymorphic call to IsApproved would call ALL the added rules. The question has also been asked in the comment to that answer but no replies.
Could you please comment on how to do this on C++ and/or (if possible) Fortran.
This example sidesteps polymorphism, where the agent is a vector of function pointers that can be dynamically added to and removed from :
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
class Person
{
public:
int _timesheet = 50;
std::string _title = "Intern";
};
class Assignment
{
public:
Person _person;
};
namespace OvertimeRule
{
bool IsApproved(Assignment const& assignment)
{
return assignment._person._timesheet >= 40;
}
}
namespace InternRule
{
bool IsApproved(Assignment const& assignment)
{
return assignment._person._title == "Intern";
}
}
int main()
{
Assignment testAssignment;
std::vector<bool(*)(Assignment const&)> assignmentAgent;
assignmentAgent.push_back(&OvertimeRule::IsApproved);
assignmentAgent.push_back(&InternRule::IsApproved);
bool const testSuccess = std::all_of(assignmentAgent.begin(), assignmentAgent.end(),
[&testAssignment] (auto const& Func)
{
return Func(testAssignment);
});
if(testSuccess)
{
std::cout << "Requirements Met!";
}
else
{
std::cout << "Requirements Not Met!";
}
}
Related
I have a class that has a constructor. I now need to make a map with it as a value how do I do this? Right now without a constructor I do.
#include <iostream>
#include <map>
using namespace std;
class testclass {
public:
int x = 1;
};
int main()
{
map<int,testclass> thismap;
testclass &x = thismap[2];
}
If I added a constructor with arguments how would I add them to the map? I basically need to do
#include <iostream>
#include <map>
using namespace std;
class testclass {
public:
int x = 1;
testclass(int arg) {
x = arg;
}
};
int main()
{
map<int,testclass> thismap;
testclass &x = thismap[2];
}
This obviously wouldn't work since it requires an argument but I can't figure a way of doing this.
This is how you can add items of your own class to your map.
Note : I used a string in testclass to better show difference
between key and value/class.
#include <iostream>
#include <string>
#include <map>
class testclass
{
public:
explicit testclass(const std::string& name) :
m_name{ name }
{
};
const std::string& name() const
{
return m_name;
}
private:
std::string m_name;
};
int main()
{
std::map<int, testclass> mymap;
// emplace will call constructor of testclass with "one", and "two"
// and efficiently place the newly constructed object in the map
mymap.emplace(1, "one");
mymap.emplace(2, "two");
std::cout << mymap.at(1).name() << std::endl;
std::cout << mymap.at(2).name() << std::endl;
}
Using std::map::operator[] requires that the mapped type is default-constructible, since it must be able to construct an element if one doesn't already exist.
If your mapped type is not default-constructible, you can add elements with std::map::emplace, but you still can't use std::map::operator[] to search, you will need to use std::map::find() or so.
That's a rather obvious feature of std::map (and very similar other std containers). Some of their operations require specific type requirements for good reasons.
There is no problem to create such a map as you suggest in the first place, however, you are restricted to method calls that do not require potential default construction. The operator[] is such a method, since in the case the element is not found, it is created. That is what does not work in your example. Just use other methods with little impact on the map usage and you can still succeed:
#include <iostream>
#include <map>
using namespace std;
class testclass {
public:
int x = 1;
testclass(int arg) {
x = arg;
}
};
int main()
{
map<int,testclass> thismap;
thismap.insert( {2, testclass(5)} );
auto element2 = thismap.find(2);
if (element2 != thismap.end()) {
testclass& thiselement = element2->second;
cout << "element 2 found in map, value=" << thiselement.x << endl;
}
auto element5 = thismap.find(5);
if (element5 == thismap.end()) {
cout << "no element with key 5 in thismap. Error handling." << endl;
}
}
Main issue: avoid operator[].
Note:
Looking at the other very good answers, there are a lot of methods that can be used without default construction. There is not "right" or "wrong" since this simply depends on your application. at and emplace are prime examples that are highly advisable.
This question already has answers here:
Why does the C++ map type argument require an empty constructor when using []?
(6 answers)
Closed 5 years ago.
I've done a lot of Googling and can't seem to figure out what's going on. I'm teaching myself C++ (I'm more familiar with Java).
I have Item Class objects that are being stored in an Inventory Class map, not as pointers. I want to retrieve one of the items from the Inventory in a function, assign it to a temp variable while I delete it from the Inventory map, and then return the object itself so something else can use it. When I originally tried using the code within my function it was returning the error (followed by the stack trace of c++ library stuff):
no matching constructor for initialization of 'Item'
::new ((void*)__p) _Tp();
I tried creating a copy constructor, but to no avail. Eventually, it worked by including an empty constructor ( Item(); ) in my header file and defining it in my cpp file ( Item::Item() {} ).
I would just like to understand why this was necessary so I can recognize it in the future to know what I'm doing.
EDIT: Upon further inspection of the error stack trace, it turned out the actual problem with with the Inventory::addItem function. When assigning an object to a map using operator[], the map first instantiates the value type to the key using the default constructor before making the assignment. No default constructor was available, so the error was returned.
It was fixed by changing the line to map.insert({key, value})
Here are the important parts of the two class files:
//item.h
#include <string>
using namespace std;
class Item {
private:
string name;
int type;
int levelReq;
public:
Item(string name, int type, int levelReq);
Item();
string getName() {return name;}
int getType() {return type;}
friend ostream &operator<<(ostream &out, const Item &item);
};
---------------------------------------------------------------
//item.cpp
#include <string>
#include "item.h"
using namespace std;
Item::Item(string n, int t, int l) : name(n), type(t), levelReq(l) {}
Item::Item() {}
ostream &operator<<(ostream &out, const Item &item) {
return out << item.name;
}
---------------------------------------------------------------
//inventory.h
#include <map>
#include "item.h"
class Inventory {
private:
map <int, Item> inventory;
int size;
bool full;
int nextFree;
void findNextFree();
public:
Inventory();
bool isFull() {return full;}
void addItem(Item item);
Item getItem(int slot);
void showInv();
};
---------------------------------------------------------------
//inventory.cpp
#include <iostream>
#include <string>
#include "inventory.h"
#include "item.h"
using namespace std;
Inventory::Inventory() {
full = false;
nextFree = 1;
size = 28;
}
void Inventory::addItem(Item item) {
if (!full) {
inventory[nextFree] = item;
findNextFree();
}
else {
cout << "Your inventory is full (Inv::addItem)";
}
}
Item Inventory::getItem(int slot) {
Item item = inventory.at(slot);
inventory.erase(slot);
full = false;
if (nextFree > slot) {
nextFree = slot;
}
return item;
}
void Inventory::findNextFree() {
nextFree++;
if (nextFree == size + 1) {
full = true;
}
else if (inventory.count(nextFree)) {
findNextFree();
}
}
I think the issue rose because you declared a constructor for your item class.
C++ will automatically generate the necessary constructors if you don't provide any custom constructors.
The necessary constructors are the default, copy and move constructors.
The moment you provide one, the default constructors won't be generated and you have this issue. This principle will also apply to structs.
Check the reference to see for yourself:
http://en.cppreference.com/w/cpp/language/default_constructor
http://en.cppreference.com/w/cpp/language/copy_constructor
http://en.cppreference.com/w/cpp/language/move_constructor
Hope this answers your question.
Is it possible to do something like
Class obj="";
Can use "" to initialize an object? I saw this in an interview, and the interviewer mentioned it is valid.
Update:
Thanks for the answers here. For the benefit of future readers, I did some search, this is called copy constructor. Some links like
copy constructor parameters
could be useful.
Yes, it really is valid. Here is an example code where it works:
#include <iostream>
#include <string>
using namespace std;
class Class {
private:
string data;
public:
Class (const char* foo) {
data = foo;
}
};
int main()
{
Class foo="bar";
return 0;
}
Before I present the code which is found at the bottom of this post I would like to talk about the issue and the fix's that I do not desire. Okay basically I've created a GUI from scratch sort of and one requirement I wanted for this was allow components to have their own click executions so if i click a button or tab etc.. It would call Component->Execute(); Well normally you would do something like a switch statement of ids and if that components ID equaled n number then it would perform this action. Well that seemed kinda dumb to me and I thought there has to be a better way. I eventually tried to incorporate a feature in JAVA where you would do like Component.AddActionListener(new ActionListener( public void execute(ActionEvent ae) { })); or something like that and I thought that this feature has to be possible in C++. I eventually came across storing void functions into a variable in which could be executed at any time and modified at any time. However I hadn't noticed an issue and that was this only worked with static functions. So below you'll see my problem. I've patched the problem by using a pointer to SomeClass however this would mean having an individual function call for every class type is there no way to store a function callback to a non-static class member without doing the below strategy? and instead doing a strategy like the commented out code?
//Main.cpp
#include <iostream> //system requires this.
#include "SomeClass.h"
void DoSomething1(void)
{
std::cout << "We Called Static DoSomething1\n";
}
void DoSomething2(void)
{
std::cout << "We Called Static DoSomething2\n";
}
int main()
{
void (*function_call2)(SomeClass*);
void (*function_call)() = DoSomething1; //This works No Problems!
function_call(); //Will Call the DoSomething1(void);
function_call = DoSomething2; //This works No Problems!
function_call(); //Will Call the DoSomething2(void);
SomeClass *some = new SomeClass(); //Create a SomeClass pointer;
function_call = SomeClass::DoSomething3; //Static SomeClass::DoSomething3();
function_call(); //Will Call the SomeClass::DoSomething3(void);
//function_call = some->DoSomething4; //Non-Static SomeClass::DoSomething4 gives an error.
//function_call(); //Not used because of error above.
function_call2 = SomeClass::DoSomething5; //Store the SomeClass::DoSomething(SomeClass* some);
function_call2(some); //Call out SomeClass::DoSomething5 which calls on SomeClass::DoSomething4's non static member.
system("pause");
return 0;
}
//SomeClass.hpp
#pragma once
#include <iostream>
class SomeClass
{
public:
SomeClass();
~SomeClass();
public:
static void DoSomething3(void);
void DoSomething4(void);
static void DoSomething5(SomeClass* some);
};
//SomeClass.cpp
#include "SomeClass.h"
SomeClass::SomeClass(void)
{
}
SomeClass::~SomeClass(void)
{
}
void SomeClass::DoSomething3(void)
{
std::cout << "We Called Static DoSomething3\n";
}
void SomeClass::DoSomething4(void)
{
std::cout << "We Called Non-Static DoSomething4\n";
}
void SomeClass::DoSomething5(SomeClass *some)
{
some->DoSomething4();
}
Secondary Fix for what I'll do not an exact answer I wanted but it meets my needs for now along with allowing additional features which would have become overly complicate had this not existed.
//Component.hpp
#pragma once
#include <iostream>
#include <windows.h>
#include <d3dx9.h>
#include <d3d9.h>
#include "Constants.hpp"
#include "ScreenState.hpp"
#include "ComponentType.hpp"
using namespace std;
class Component
{
static void EMPTY(void) { }
static void EMPTY(int i) { }
public:
Component(void)
{
callback = EMPTY;
callback2 = EMPTY;
callback_id = -1;
}
Component* SetFunction(void (*callback)())
{
this->callback = callback;
return this;
}
Component* SetFunction(void (*callback2)(int), int id)
{
this->callback_id = id;
this->callback2 = callback2;
return this;
}
void execute(void)
{
callback();
callback2(callback_id);
}
}
The syntax for pointers-to-member-functions is as follows:
struct Foo
{
void bar(int, int);
void zip(int, int);
};
Foo x;
void (Foo::*p)(int, int) = &Foo::bar; // pointer
(x.*p)(1, 2); // invocation
p = &Foo::zip;
(x.*p)(3, 4); // invocation
Mind the additional parentheses in the function invocation, which is needed to get the correct operator precedence. The member-dereference operator is .* (and there's also ->* from an instance pointer).
I have a large series of functions that all look very similar: they take the same arguement type and return strings.
std::string f1(T arg);
std::string f2(T arg);
std::string f3(T arg);
std::string f4(T arg);
.
.
.
In a loop, they are used according to one of the variables inside the struct T. Currently to do this, I just have a large switch/case block in my code.
Is there any better coding style for doing this? The large block of code looks very weird.
I wish c++ could be like python and do eval("f" + str(i) + "(arg))"
The block is something like this:
std::string out = "";
switch (arg.tag){
case 1:
out += f1(arg);
break;
case 2:
out += f2(arg);
break;
.
.
.
}
for about 2 dozen cases
With C++11 you can do this fairly easily with std::function and a map:
#include <map>
#include <functional>
#include <string>
#include <iostream>
std::string f1(int) { return "f1"; }
std::string f2(int) { return "f2"; }
std::map<int, std::function<std::string(int)> > funcs = {
{1,f1},
{2,f2}
};
int main() {
std::cout << funcs[1](100) << "\n";
}
Without C++11 you'll want to either use Boost instead of std::function or roll your own type instead. You could use plain old function pointers but that would rule out some handy things (like std::bind/boost::bind, functor objects, lambda functions. You could also define a type hierarchy with an interface that your functions implement for example the following works in C++03 except for the way the map is initialised:
#include <map>
#include <functional>
#include <string>
#include <iostream>
std::string f1(int) { return "f1"; }
std::string f2(int) { return "f2"; }
std::map<int, std::string(*)(int)> funcs = {
std::make_pair(1,f1),
std::make_pair(2,f2)
};
int main() {
std::cout << funcs[1](100) << "\n";
}
or this which lets you write any kind of functor object you like:
#include <map>
#include <string>
#include <iostream>
struct thing {
virtual std::string operator()(int) const = 0;
};
struct f1 : thing {
std::string operator()(int) const { return "f1"; }
};
struct f2 : thing {
std::string operator()(int) const { return "f2"; }
};
// Note the leak - these never get deleted:
std::map<int, thing*> funcs = {
std::make_pair(1,new f1),
std::make_pair(2,new f2)
};
int main() {
std::cout << (*funcs[1])(100) << "\n";
}
One way to emulate the Eval() is to have a map. The key of the map would be the names of the functions, and the values would be the pointers to the corresponding functions.
In this case you will be able to call the functions needed with the map's operator[] by their name. This will somehow emulate the eval("f" + str(i) + "(arg))" behavior, though it may still not be the best solution for you.