C++ primer 6th Exercise 10.8 - c++

You can describe a simple list as follows:
The simple list can hold zero or more items of some particular type.
You can create an empty list.
You can add items to the list.
You can determine whether the list is empty.
You can determine whether the list is full.
You can visit each item in the list and perform some action on it.
As you can see, this list really is simple; it doesn’t allow insertion or deletion, for example.
Design a List class to represent this abstract type.You should provide a list.h
header file with the class declaration and a list.cpp file with the class method
implementations.You should also create a short program that utilizes your design.
The main reason for keeping the list specification simple is to simplify this programming exercise.You can implement the list as an array or, if you’re familiar with
the data type, as a linked list. But the public interface should not depend on your
choice.That is, the public interface should not have array indices, pointers to nodes,
and so on. It should be expressed in the general concepts of creating a list, addingan item to the list, and so on.The usual way to handle visiting each item and performing
an action is to use a function that takes a function pointer as an argument:
void visit(void (*pf)(Item &));
Here pf points to a function (not a member function) that takes a reference to Item
argument, where Item is the type for items in the list.The visit() function applies
this function to each item in the list.You can use the Stack class as a general guide.
What I want to know is why should I use pointer-to-functions? what's the difference between using usual member function and using the function that uses pointer-to-function as argument? (in this case, using void visit(void (*pf)(Item &)))?

Function Pointers
Imagine you have a function which takes a number and squares it and returns it. And you have a list whose each member you want squared. How do you do that?
You either write another function which accepts an array, loops through it and converts every element to its square.
You have a function which accepts an array and a function which can transform one single element. You apply the function to each element of the array.
Both perform the same task. You might think the previous case is easier to implement. You wont have to deal with function pointers after all.
However what if you have say 20 functions which can double, triple, cube, square, etc. a single parameter passed to them. If you follow the first route, you have to write 20 different functions (with probably different names). However now the latter makes sense. You just declare the individual functions. And call the transformer function by passing the array and any of the 20 functions via pointer to achieve your task.
An example is std::transform in the C++ STL.
Working stuff :
#include <iostream>
#include <vector>
typedef double (*function)(double);
void transformer(std::vector<double>& to_transform, function f)
{
for(auto it = to_transform.begin(); it != to_transform.end(); ++it)
*it = f(*it);
}
void print(const std::vector<double>& v)
{
std::cout << "[ ";
for(double val : v)
std::cout << val << " ";
std::cout << "]" ;
}
double f1(double a) { return a*2; }
double f2(double a) { return a*3; }
double f3(double a) { return a/2; }
double f4(double a) { return a*a*a; }
int main() {
std::vector<double> array = { 2.3, 5.6, 4.5, 7.8, 2.3 };
std::vector<function> function_ptrs = { &f1, &f2, &f3, &f4 };
std::size_t val ;
std::cout << "The original : " ;
print(array);
std::cout << "\nChoose a function (1-4) : ";
std::cin >> val;
std::cout << "The array after applying function " << val << " is : ";
transformer(array, function_ptrs[(val - 1) % function_ptrs.size()]);
print(array);
return 0;
}
I am assuming you have a C++11 compliant compiler. The above code has 4 functions which take in a double and transform it somehow. The transformer function applies such a function to a vector of doubles. The function pointers are stored in a vector too - Yes an array of function pointers. The functions can be called as a normal element is accessed via indexing. On choosing an option, the appropriate function is called and executed by transformer element wise on the vector of doubles.
You can further improve it with templates (instead of fixed doubles) and using std::transform from STL.
C++11 Lambda Expressions
Also, with C++11, you should prefer lambdas and not function pointers. Lambdas are written as
[ ... capture list ... ] ( params ) -> return_type (optional) { body }
A solution with lambda would be something like this :
#include <iostream>
#include <algorithm>
#include <vector>
template <typename T>
void print(const std::vector<T>& v)
{
std::cout << "[ ";
for(T val : v)
std::cout << val << " ";
std::cout << "]" ;
}
int main() {
std::vector<double> array = { 2.3, 5.6, 4.5, 7.8, 2.3 };
std::cout << "The original : " ;
print(array);
std::cout << "\nThe array after transforming : " ;
std::transform(array.begin(), array.end(), array.begin(),
[](double x) { return x * x; });
print(array);
return 0;
}
Function Objects
You can declare your own class which just overloads the () operator (which makes the object callable) and does an identical job as a function pointer (can be passed to a function and called) i.e. in this case the class would look like :
class double_the_value
{
double operator()(double val) const { return val * 2.0 ; }
};
double_the_value f ;
std::cout << f(3.0) ; // outputs 6.0
An actual usage would be the std::unordered_map container where if you are using your own class types for keys, you will need to provide a key hasher - which can be a function object. This is demonstrated in detail by this answer.

When you're creating a true abstract list you have no idea what functions you will need to call on the objects, so your usual member functions won't be enough. You can't write all of them.
A common and easier alternative to this pattern is to return a copy of the full collection or expose iterators to the first and last element. But this can cause performance issues and can be risky - a copy can be expensive and is usually unnecessary, and if you use iterators they can become invalid if the collection changes beneath you. The visitor pattern hides all this by giving you better encapsulation and keeps the iteration loop within the class, where it usually belongs.
It's an additional layer of abstraction. If you have a collection of items, you usually want to do something to some (or all) of the items in that collection. The visitor pattern lets you inspect each item and then do something.

Related

C++ Member Function That Returns A Value of Two other member functions

I had this question on a test about a month ago and I still can't seem to understand it completely and quite frankly it's driving me crazy. I will include the question at the bottom. But, it's asking to create a single parameter constructor that creates a new "Vector" (the name of the class) which is the sum of two others. The vector class I made has a function set/get x and set/get y. My hang up is I can't seem to figure out how to make a function that adds the two x's and y's together from vector and vector1 to create a new Vector...call it vector2. I'll include everything I got so far. Thanks to anyone willing to make it through the wall of text as confusing as it must be haha.
Write a class Vertor with the following properties and place the class in a separate header file :
Add member function with a single parameter of another vector and returns a new vector that is the sum of the two (to add vectors you sum the components, for example, Cx = Ax + Bx and Cy = Ay + By).
Write a program that includes the Vector header file, constructs two different vectors and demonstrates the magnitude, angle, and add functions.
Data Members
vector
x component
y component
Member Functions
Set and Get functions for all data members
Magnitude member function
Angle member function (angle = inverse tangent(y / x))
ps I hope I am not doing anything wrong by uploading this and asking I have waited this entire time because I didn't want to break some sort of rule in the community....that I am honestly desperate to become a part of. I've dreamed of doing this my whole life and finally....ahh i digress sorry thanks guys
Oh...my code
#include "Vertor.h"
#include <iostream>
int main()
{
// creates a vector class
Vector vector;
vector.setXcom(4); // sets X
vector.setYcom(12); // sets Y
Vector vector1; // Creates another vector
vector1.setXcom(3);
vector1.setYcom(52);
Vector vector2; // constructs another vector that returns the sum of two other vectors
cout << vector.getXcom() << endl;
cout << vector.getYcom() << endl;
cout << vector.getMag() << endl;
cout << vector.getAng() << endl;
cout << vector1.getXcom() << endl;
cout << vector1.getYcom() << endl;
cout << vector1.getMag() << endl;
cout << vector1.getAng() << endl;
}
#include<iostream>
using namespace std;
// initalize variables
double xcomponent, ycomponent;
double ans, anns, annns;
class Vector // creates Vector class
{
public:
void setXcom(double x) // setX function
{
xcomponent = x;
}
void setYcom(double y) // setY function
{
ycomponent = y;
}
double getXcom() // getX function
{
return xcomponent;
}
double getYcom() // getY function
{
return ycomponent;
}
double getMag() // get magnitude function
{
double ans = sqrt((xcomponent * xcomponent) + (ycomponent * ycomponent));
return ans;
}
double getAng() // get angle function
{
double annns = atan(xcomponent / ycomponent);
return annns;
}
// setnewvec function to make a new vector from two others
void setNewVec(int a, int b)
{
xcomponent = a;
ycomponent = b;
}
// NOT SURE
Vector getNewVec(int a, int b)
{
return a + a;
return b + b;
}
};
So you have an absolutely fundamental misunderstanding or gap in your knowledge about how objects work, and this task will be impossible until you sort that out.
To illustrate here's a simpler example written in the style of your code above. I'll follow that with the same example written as it should be. This example is a simple Person class which has an age 'component'.
int age;
class Person
{
public:
void setAge(int a) { age = a; }
int getAge() { return age; }
};
int main()
{
Person fred;
fred.setAge(22);
Person mary;
mary.setAge(33);
cout << "Fred is " << fred.getAge() << " and Mary is " << mary.getAge() << endl;
}
If you run this program the output will be Fred is 33 and Mary is 33. Both the people have the same age even though you set them as different in the program.
The problem is that although this program has two people it only has one age. So it's literally impossible for the two people to have different ages.
Here's the program written correctly. The crucial difference is that the age variable is inside the class. This means that each Person object gets it's own age.
class Person
{
public:
void setAge(int a) { age = a; }
int getAge() { return age; }
private:
int age;
};
int main()
{
Person fred;
fred.setAge(22);
Person mary;
mary.setAge(33);
cout << "Fred is " << fred.getAge() << " and Mary is " << mary.getAge() << endl;
}
Now the output is Fred is 22 and Mary is 33 as it should be.
First thing you need to do, is to move xcomponent and ycomponent to inside the object. Right now they are global variables which means they share values in all objects you create (and outside object too).
I'm gonna assume you've learned about structures before moving to objects. It's pretty hard to understand object without knowing structures first.
Structures and classes are very similar. They both are containers for variables. Classes are a little more advanced version that usually hides the raw data and instead provides member functions (sometimes called methods) that allow to manipulate the data inside in a more convenient way.
Anyway, when you create a new object of a class, you create it with a new copy all member variables (fields) inside. This way, they can have different values for each object.
Your code is pretty easy to fix in that regard. Just move definition of these variables inside your class.
Old code:
double xcomponent, ycomponent;
double ans, anns, annns;
class Vector // creates Vector class
{
public:
//...
};
New code:
class Vector // creates Vector class
{
double xcomponent, ycomponent;
double ans, anns, annns;
public:
//...
};
Now we can work on the return value.
Your return value of getNewVec is all right. You've declared that you want to return an object of type Vector and this is exactly what you want.
However, the function should also take a single vector as an argument. Right now you have tho arguments int a and int b, none of which is a Vector. We need to change that to Vector otherVector to do what your assignment said.
The call of the function looks like this: someVector.getNewVec(someOtherVector).
When it runs, you have two vectors accessible inside of it. The first of them is the one on which the function was called. You have direct access to its fields. The second one is of course the argument otherVector. You can access its fields through its member functions. (Or you can access directly its private fields because you're in a member function of its class.)
Now you need to construct the new vector.
The simplest way is to just create it and assign the values one by one:
Vector getNewVec(Vector otherVector)
{
Vector newVector;
newVector.setXcom(xcomponent + otherVector.getXcom());
newVector.setYcom(ycomponent + otherVector.getYcom());
return newVector;
}
or:
Vector getNewVec(Vector otherVector)
{
Vector newVector;
newVector.setXcom(xcomponent + otherVector.xcomponent);
newVector.setYcom(ycomponent + otherVector.ycomponent);
return newVector;
}
or if you really want:
Vector getNewVec(Vector otherVector)
{
Vector newVector;
newVector.setXcom(this->getXcom() + otherVector.getXcom());
newVector.setYcom(this->getYcom() + otherVector.getYcom());
return newVector;
}
(this is a pointer the object your inside of. You have access to it from each member function.)
I recommend the second option.
Some additional stuff you can read about if your interested...
(I'm not gonna go into any details here.)
Constructors
You can have a special member function that is called when object it's created that is supposed to set initial values to the fields.
It is written similar to a function, except is doesn't have a return value and it's name is always the same as the name of the class.
Vector(int x, int y)
{
xcomponent = x;
ycomponent = y;
}
That allows to create an abject and assign the values in one line so instead of:
Vector newVector;
newVector.setXcom(12);
newVector.setYcom(42);
you can have:
Vector newVector(12, 42);
You can have more than one constructor with different list of arguments.
You can create an operator instead of a normal function. An operator is a function with specific name and arguments that can be called similarly to built-in mathematical operations.
Operator for addition looks like this:
Vector operator+(Vector otherVector)
//the body is the same as getNewVec
You could call it like a normal member function:
someVector.operator+(someOtherVector)
but a better way of writing it is:
someVector + someOtherVector

Inserting the Object into map or array or victor as a constructor of the object

hello I am beginner in cpp, is there away that I can save an object automaticaly after being created to a map or any kind of containers? in this simple example i can say that the problem is that the object is not created yet so how can I refer to an uncreated object in the constructor.?
class A {
public:
A(parameter){
map.emplace(key,object);//what should I write in the second field ?
}
};
As suggested in a comment, you can use a static method:
#include <map>
#include <iostream>
struct A {
int x;
A(int x) : x(x) {}
static auto create_in_map(int key,int x, std::map<int,A>& m) {
return m.emplace(key,x).first;
}
};
int main() {
std::map<int,A> map;
auto it = A::create_in_map(1,2,map);
std::cout << "key: " << it->first << " value: " << it->second.x;
}
Note that standard containers own their elements, ie you do not want to first create an A and then place it in the map, because you would end up with two instances: The one you created and the copy inside the map. emplace takes the key and parameters for As constructor and creates the instance directly in the map. It returns a std::pair<iterator,bool>, the iterator points to the inserted element and the bool indicates whether the element actually has been inserted (it isn't when the key is already present). In the code I ignored the bool and only returned the iterator. The iterators ->first is the key and its ->second is the A the was created in the method.
Last but not least, the above code is only for illustration. There is no need for that static method. You should simply write map.emplace(1,2) in main.

How would I approach a function lookup-table with member functions of different classes?

I am being passed an array with values that I need to pass on to a few objects to store them. The array is two-dimensional of the form
{{int ID, int iNewValue}, ...}
I do not know which or how many values are updated but the ID is unique and doesn't change. I am told the ID <-> value pair once so I could just use a massive switch statement to check the ID and pass the value to the correct object and correct setter function. I thought I could make it more efficient and convenient and use a lookup-table where the index is the ID and the element is a pointer to the correct member function:
for (int i = 0; i < iNewValueLength; i++)
{
int ID = arrayNewValues[i][0];
int iNewValue = arrayNewValues[i][1];
(object.*lookup_table[ID])(iNewValue);
}
However, I am running into two issues:
I have multiple objects per class so I would need to be able to have individual entries in my lookup_table for different individual objects (even though they have the same functions). As an example, I have different humans and get updates to their height so I save the height setter function of each individual "human-object" and pass the updated height value to the correct object when I get an update. lookup_table[5] might point to the height setter function of human-object number 2. I am having trouble understanding how to implement this, I've stumbled over this question. Is this what I want or is there another way?
I have multiple different classes so I can't put it all inside one lookup table (or can I?). Since I have no control over how the IDs are assigned which means I cannot they assume they are in order and do something like
if (ID < 10) (object1.*lookup_table_object1[ID])(iNewValue);
else if (ID < 20) (object2.*lookup_table_object2[ID])(iNewValue);
...
What should I do?
Thanks in advance for any help or pointers in the right direction!
Consider the following exemplary classes that have some member functions accepting int arguments:
struct X {
void f1(int i) const { std::cout << "X::f1(" << i << ")\n"; }
void f2(int i) const { std::cout << "X::f2(" << i << ")\n"; }
};
struct Y {
void f1(int i) const { std::cout << "Y::f1(" << i << ")\n"; }
void f2(int i) const { std::cout << "Y::f2(" << i << ")\n"; }
};
Now, suppose you have some objects of these classes:
X x;
Y y;
To accomplish your goal, you can create a lookup table with value type std::function<void(int)>:
std::map<int, std::function<void(int)>> m;
Then, you can populate such a lookup table with lambdas (or use std::bind in the old way) that represent particular combinations of objects (possibly different objects of different classes) and their member functions:
m[1] = [&x](int i){ x.f1(i); };
m[2] = [&x](int i){ x.f2(i); };
m[3] = [&y](int i){ y.f1(i); };
m[4] = [&y](int i){ y.f2(i); };
Finally, to invoke these functions:
m[3](12);
m[2](-1);
Which outputs:
Y::f1(12)
X::f2(-1)
Live demo: https://wandbox.org/permlink/GGPaNJ15EIm9g5gy.
Just beware of possible dangling references in lambdas. The referenced objects generally need to exist as long as the entries in the lookup table are linked to them.

Print Object that is pointed to

I try to print values from my object class, but I am unable to properly access the information stored at the pointer. Below I have defined a simple struct.
When compiled, I get an error:
no match for 'operator<<' (operand types are 'std::ostream {aka std::basic_ostream<char>}' and 'std::vector<int>')
void PrintNode(Node *node) { cout << node->key << endl; }
struct Node
{
vector<int> key;
int parent;
Node(vector<int> x, int y){ key = x; parent = y; }
void PrintNode(Node* node) { cout << node->key << endl; }
};
I call my PrintNode in my BFS function:
void BFS( vector<int> permutation, int n ) {
vector<Node*>Pointers;
queue<Node*> Queue;
Node* start = new Node(permutation, -1);
Node::PrintNode( start );
Pointers.push_back( start );
}
I don't understand why I am unable to cout the integer vector stored in .key of the node object. I believe that I am dereferencing the pointer correctly with node->key.
The standard library doesn't support direct iostreams output of a vector. But you can easily define such an operation. Just do it with a loop.
std::cout cannot handle raw vectors, you must convert it to an array which is can process first. You can do this using vector's .data() method
Example:
void PrintNode(Node* node) { cout << node->key.data() << endl; }
I try to print values from my object class, but I am unable to properly access the information stored at the pointer. Below I have defined a simple struct.
The simple answer to this question is the fact that std::vector<type, allocator> does not have an overload for the std::ostream::<< operator. Hence when you try to print out the entire vector of keys, it won't work the way you expect it to. I have seen several answers on other posts which suggest overloading the << operator for std::vector but unless you know what you are doing I would avoid doing this for several reasons, one of them being global namespace pollution and the second being incorrect handling of the overloading itself.
Also, please stop doing using namespace std;. It will not help you in any way and just make things worse in the most unexpected ways.
Here are some fixes which may help.
Part 1 - Node struct
struct Node : public std::enable_shared_from_this<Node>
{
std::vector<int> keys;
int parent;
Node(vector<int> x, int y) : keys(x), parent(y){}
Node(const Node& rhs): keys(rhs.keys), parent(rhs.parent) {}
Node(Node&& rhs) noexcept: keys(std::move(rhs.keys)), parent(rhs.parent){}
void PrintNode()
{
for (auto& key : node->keys)
cout << key << "\n";
}
};
Part 2 BFS Code
void BFS(std::vector<int>& permutation, int n )
{
/* I don't see the real value in creating pointers for your case. You can easily live with an instance of the class Node. This also gives you scoped initialization as the pointers vector goes out of scope, your nodes will get deallocated too. at least in the context, you have posted above, that seems desirable.
However, if you insist on creating pointers, you can use smart pointers.
*/
std::vector<std::shared_ptr<Node>> pointers;
std::queue<std::shared_ptr<Node>> queue; // not used??
auto start = std::make_shared<Node>(permutation, -1); // make a shared pointer
/* PrintNode in your code is an instance level function. Invoke it using the scope resolution operators . or ->. If you insist on doing it your way, then declare the function static. However, that has its own quirks and you need to understand static functions before you do this. */
start->PrintNode();
pointers.push_back(std::move(start)); // add your pointer to the vector.
}
That said the code excerpt you have posted makes little sense. I have just provided fixes for the parts you have provided. Does not guarantee that it will work in the larger context you may have at hand.

C++ distinguish Lambdas from Function pointers inside a vector

I'm writing a little event manager class where I store some function pointers inside a vector. I use std::function<void(int)> as vector type, I tested inserting inside it lambdas and normal functions and it works:
void t(int p){
/*things*/
}
[...]
event.bind([](int p){/*things*/});
event.bind(t);
Now, (at a certain point I need to delete lambdas but not functions,) my question is:
Is it possible to distinguish lambdas from functions? If yes, how?
EDIT:
Since I clarified my doubts, this question becomes just what the title says
The real answer is: you don't want to do this. It defeats the point of type-erasing functors if you actually want to know the original type also in case of whatever. This just smells like bad design.
What you are potentially looking for is std::function::target_type. This is a way to pull out the underlying type_info of the target function that the function object is storing. Each type_info has a name(), which can be demangled. Note that this is a very deep rabbit hole and you're basically going to have to hard-code all sorts of weird edge-cases. As I've been doing thanks to Yakk's very loving help.
Different compilers mangle their lambda names differently, so this approach doesn't even resemble portability. Quick checking shows that clang throws in a $ while gcc throws {lambda...#d}, So we can attempt to take advantage of that by writing something like:
bool is_identifier(std::string const& id) {
return id == "(anonymous namespace)" ||
(std::all_of(id.begin(), id.end(),
[](char c){
return isdigit(c) || isalpha(c) || c == '_';
}) && !isdigit(id[0]));
}
bool is_lambda(const std::type_info& info)
{
std::unique_ptr<char, decltype(&std::free)> own {
abi::__cxa_demangle(info.name(), nullptr, nullptr, nullptr),
std::free
};
std::string name = own ? own.get() : info.name();
// drop leading namespaces... if they are valid namespace names
std::size_t idx;
while ((idx = name.find("::")) != std::string::npos) {
if (!is_identifier(name.substr(0, idx))) {
return false;
}
else {
name = name.substr(idx+2);
}
}
#if defined(__clang__)
return name[0] == '$';
#elif defined(__GNUC__)
return name.find("{lambda") == 0;
#else
// I dunno?
return false;
#endif
}
And then throw that in your standard erase-remove idiom:
void foo(int ) { }
void bar(int ) { }
long quux(long x) { return x; }
int main()
{
std::vector<std::function<void(int)>> v;
v.push_back(foo);
v.push_back(bar);
v.push_back(quux);
v.push_back([](int i) { std::cout << i << '\n';});
std::cout << v.size() << std::endl; // prints 4
v.erase(
std::remove_if(
v.begin(),
v.end(),
[](std::function<void(int)> const& f){
return is_lambda(f.target_type());
}),
v.end()
);
std::cout << v.size() << std::endl; // prints 3
}
No, not in general.
A std::function<void(int)> can store a function pointer to any function that can be called by passing a single rvalue int. There are an infinite number of such signatures.
The type of a lambda is an unique anonymous class for each declaration. Two distinct lambdas do not share any type relationship.
You can determine of a std::function<void(int)> stores a variable of a specific type, but in both the function pointer and lambda case there is an unbounded number of different types that can be stored in the std::function to consider. And you can only test for "exactly equal to a type".
You can access the type id information, but there is no portable representation there, and generally using that information for anything other than identity matching (and related) or debugging is a bad idea.
Now, a restricted version of the question (can you tell if a std::function<void(int)> contains a function pointer of type void(*)(int)) is easy to solve. But in general, doing so remains a bad idea: first, because it is delicate (code far away from the point you use it, like a subtle change to the function signature, can break things), and second, inspecting and changing your behavior based on the type stored in a std::function should only be done in extreme corner cases (usually involving updating your code from using void* style callbacks to std::function style callbacks).
Be it a function pointer or lambda, it ends up as a std::function<void(int)> in the vector. It is then std::function<void(int)>'s responsibility to manage the function pointer or lambda, not yours. That means, you just remove the std::function<void(int)>s you want from the vector. The destructor of std::function<void(int)> knows how to do things right. In your case, that would be doing nothing with function pointers and invoking the destructor of lambdas. std::function<void(int)> enables you to treat different things in a nice and uniform way. Don't misuse it.
NOTE: This answer presupposes that there is a finite, distinct number of function signatures that may be assigned as event handlers. It assumes that assigning any-old function with the wrong signature is a mistake.
You can use std::function::target to determine which ones are the function pointers and by process of elimination figure out which ones must be the lambdas:
void func1(int) {}
void func2(double) {}
int main()
{
std::vector<std::function<void(int)>> events;
events.push_back(func1);
events.push_back([](int){});
events.push_back(func2);
for(auto& e: events)
{
if(e.target<void(*)(int)>())
std::cout << "funcion int" << '\n';
else if(e.target<void(*)(double)>())
std::cout << "funcion double" << '\n';
else
std::cout << "must be lambda" << '\n';
}
}
This works because std::function::target returns a null pointer if the parameter type doesn't match.
Single variable example:
void func(int) {}
int main()
{
std::function<void(int)> f = func;
if(f.target<void(*)(int)>())
std::cout << "not a lambda" << '\n';
}