This is a sequel to a related post which asked the eternal question:
Can I have polymorphic containers with value semantics in C++?
The question was asked slightly incorrectly. It should have been more like:
Can I have STL containers of a base type stored by-value in which the elements exhibit polymorphic behavior?
If you are asking the question in terms of C++, the answer is "no." At some point, you will slice objects stored by-value.
Now I ask the question again, but strictly in terms of C++11. With the changes to the language and the standard libraries, is it now possible to store polymorphic objects by value in an STL container?
I'm well aware of the possibility of storing a smart pointer to the base class in the container -- this is not what I'm looking for, as I'm trying to construct objects on the stack without using new.
Consider if you will (from the linked post) as basic C++ example:
#include <iostream>
using namespace std;
class Parent
{
public:
Parent() : parent_mem(1) {}
virtual void write() { cout << "Parent: " << parent_mem << endl; }
int parent_mem;
};
class Child : public Parent
{
public:
Child() : child_mem(2) { parent_mem = 2; }
void write() { cout << "Child: " << parent_mem << ", " << child_mem << endl; }
int child_mem;
};
int main(int, char**)
{
// I can have a polymorphic container with pointer semantics
vector<Parent*> pointerVec;
pointerVec.push_back(new Parent());
pointerVec.push_back(new Child());
pointerVec[0]->write();
pointerVec[1]->write();
// Output:
//
// Parent: 1
// Child: 2, 2
// But I can't do it with value semantics
vector<Parent> valueVec;
valueVec.push_back(Parent());
valueVec.push_back(Child()); // gets turned into a Parent object :(
valueVec[0].write();
valueVec[1].write();
// Output:
//
// Parent: 1
// Parent: 2
}
You certainly can't have a polymorphic array (or vector). The requirement that the elements of an array be stored contiguously in memory is fundamentally incompatible with the fact that different derived class types may have different sizes.
None of the standard library containers allow for storing objects of different derived class types in a single container.
Just for fun, based on James's comment about a template-based system, I came up with this Vector-like implementation. It's missing lots of features, and may be buggy, but it's a start!
#include <iostream>
#include <vector>
#include <boost/shared_ptr.hpp>
template <typename T>
class Vector
{
public:
T &operator[] (int i) const { return p[i]->get(); }
template <typename D>
void push_back(D &x) { p.push_back(ptr_t(new DerivedNode<D>(x))); }
private:
class Node
{
public:
virtual T &get() = 0;
};
template <typename D>
class DerivedNode : public Node
{
public:
DerivedNode(D &x) : x(x) {}
virtual D &get() { return x; }
private:
D x;
};
typedef boost::shared_ptr<Node> ptr_t;
std::vector<ptr_t> p;
};
///////////////////////////////////////
class Parent
{
public:
Parent() : parent_mem(1) {}
virtual void write() const { std::cout << "Parent: " << parent_mem << std::endl; }
int parent_mem;
};
class Child : public Parent
{
public:
Child() : child_mem(2) { parent_mem = 2; }
void write() const { std::cout << "Child: " << parent_mem << ", " << child_mem << std::endl; }
int child_mem;
};
int main()
{
Vector<Parent> v;
v.push_back(Parent());
v.push_back(Child());
v[0].write();
v[1].write();
}
First of all, your requirements are still not perfectly clear. I will assume that you want "inline storage" for the container; so, for example, in a "polymorphic" vector, all elements would be adjacent in memory (with only padding in between as needed for correct alignment).
Now, it is possible if you're willing to provide an exhaustive list of all types that you're going to put into the container at compile-time. The most straightforward implementation would be to use a union of all possible types as the type of the backing array - that would ensure enough size and proper alignment, and same O(1) access by index, at the cost of some wasted space on elements of smaller-size types. I can go into this with more detail if you want.
If the list of types is now known in advance, or if you do not want that kind of overhead, then you'd have to maintain a separate index of pointers (or offsets from the beginning of the backing store) to elements, so that you can do O(1) access. Also, given the alignment issues, I'm not sure if you could even do that in fully portable C++03, though you definitely can in C++0x.
Related
I know this question gets asked a lot, but I have a specific use case, so I don't think it's a duplicate!
I have an abstract base class:
template<int N>
class Child;
class Base
{
public:
// Factory-like generation of children as Base
static Ptr<Base> New(int baseN)
{
if (baseN == 2) return new Child<2>();
else if (baseN == 3) return new Child<3>()
}
// Update
virtual void update() = 0;
};
And I'm writing some children of Base as class templates (on an int):
template<int N>
class Child
:
public Base
{
// Member, N is not the size of matrix, more like the size of a component in matrix
Matrix<N> m_member;
public:
// Implement update
virtual void update();
// Should call the passed callable on m_member
virtual void execute(std::function<void(Matrix<N>&)>&);
};
// Force compilation of Child<N> for some values of N (of interest, including 3) here
// Then,
int baseN = 3;
Ptr<Base> obj = Base::New(baseN); // will get me a Child<3> as a Base object
auto callable = [](Matrix<3>) ->void {};
// Can I access Child<3>::m_member ??
// Can't cast to Child<baseN> (baseN is not constexpr) and don't want to
// But want to do something like:
obj->execute(callable);
// Which forwards 'callable' to the method from concrete type, probably using a cast?
In short, I need to have some sort of access to m_member from the declared Base object.
Preferably, a way to call Child<N>::execute from Base without making Base a template on N too.
Things I've tried/thought-of include:
'Type erasure' of Matrix<N> by hiding them behind an interface, but because Matrix<N>'s interface strongly depends on N, doing that renders the classes useless (think: Vector<N>& Matrix<N>::diag() for example)
Can Base::New do anything to record what concrete type it creates? I doubt that because types are not objects.
EDIT: (Btw this is C++11)
So, I accidentally figured out a way to do this; but I don't quite understand why the following works (Not well versed into assembly yet):
I'm using a Database for objects (unordered_map<string, object*> where object is a class that every registered object has to inherit from).
When a Child is created, we register it to a database with a name of Child<N>.
Then, at application-level code, there is a findChild<int N> template which employs compile-time recursion to find which concrete class was the Base pointer created from (At runTime, by dynamicCasting and testing). When It finds it, it can cast it to void* through a static method (findChild<N>::castToConcrete)
What's interesting is that we can somehow use findChild<0> to access the findChild<N> in question if Child<N> is polymorphic. This forces us to have at most one object of Child (for all possible Ns) and I certainly can live with that.
You can see and inspect a minimal code example here: https://onlinegdb.com/CiGR1Fq5z
What I'm so confused about is that Child<0> and other Child<N> are completely different types; So how can we access one's members from a pointer to another type? I'm most likely relying on UB and even fear there is a stack smacking of some sort!
For reference, I'm including the code here in case the link dies.
#include <unordered_map>
#include <vector>
#include <functional>
#include <iostream>
using namespace std;
#ifndef MAX_N_VALUE
#define MAX_N_VALUE 10
#endif // !MAX_N_VALUE
// ------------------ Lib code
// A dummy number class for testing only
template <int N> struct Number { constexpr static int value = N; };
// Objects to register to the database
struct object
{
// Members
string name;
// construction/Destruction
object(const string& name) : name(name) {}
virtual ~object(){};
};
// Database of objects
struct DB
: public unordered_map<string, object*>
{
// See if we can the object of name "name" and type "T" in the DB
template <class T>
bool found(const string& name) const
{
unordered_map<string,object*>::const_iterator iter = find(name);
if (iter != end())
{
const T* ptr = dynamic_cast<const T*>(iter->second);
if (ptr) return true;
cout << name << " found but it's of another type." << endl;
return false;
}
cout << name << " not found." << endl;
return false;
}
// Return a const ref to the object of name "name" and type "T" in the DB
// if found. Else, fails
template <class T>
const T& getObjectRef(const string& name) const
{
unordered_map<string,object*>::const_iterator iter = find(name);
if (iter != end())
{
const T* ptr = dynamic_cast<const T*>(iter->second);
if (ptr) return *ptr;
cout << name << " found but it's of another type." << endl;
abort();
}
cout << name << " not found." << endl;
abort();
}
};
// Forward declare children templates
template<int N>
class Child;
// The interface class
struct Base
{
// Construction/Destruction
protected:
static unsigned counter;
Base(){}
public:
virtual ~Base() {}
// Factory-like generation of children as Base
// THIS New method needs to know how to construct Child<N>
// so defining it after Child<N>
static Base* New(int baseN, DB& db);
// Update
virtual void update() = 0;
// Call a callable on a child, the callable interface
// however is independent on N
virtual void execute(std::function<void(Base&)>& callable)
{
callable(*this);
}
};
unsigned Base::counter = 0;
// The concrete types, which we register to the DB
template<int N>
struct Child
:
public Base, public object
{
// members
vector<Number<N>> member;
// Construction/Destruction
Child() : Base(), object(string("Child") + to_string(N) + ">"), member(N, Number<N>()) {}
virtual ~Child() {}
// Test member method (Has to be virtual)
virtual vector<Number<N>> test() const
{
cout << "Calling Child<" << N << ">::test()" << endl;
return vector<Number<N>>(N, Number<N>());
}
// Implement update
virtual void update()
{
cout << "Calling Child<" << N << ">::update()" << endl;
};
};
// New Base, This can be much more sophisticated
// if static members are leveraged to register constructors
// and invoke them on demand.
Base* Base::New(int baseN, DB& db)
{
if (baseN == 2)
{
Child<2>* c = new Child<2>();
db.insert({string("Child<")+std::to_string(2)+">", c});
return c;
}
if (baseN == 3)
{
Child<3>* c = new Child<3>();
db.insert({string("Child<")+std::to_string(3)+">", c});
return c;
}
return nullptr;
}
// Finder template for registered children
template<int N>
struct findChild
{
// Concrete Type we're matching against
using type = Child<N>;
// Stop the recursion?
static bool stop;
// Compile-time recursion until the correct Child is caught
// Recursion goes UP in N values
static void* castToConcrete(const DB& db, Base* system)
{
if (N > MAX_N_VALUE) stop = true;
if (stop) return nullptr;
if (db.found<type>(string("Child<")+to_string(N)+">"))
{
type* ptr = dynamic_cast<type*>(system);
return static_cast<void*>(ptr);
}
// NOTE: This should jump to the next "compiled" child, not just N+1, but meh;
return findChild<N+1>::castToConcrete(db, system);
}
};
// Activate recursive behaviour for arbitraty N
template<int N>
bool findChild<N>::stop = false;
// Explicit specialization to stop the Compile-time recursion at a decent child
template<>
struct findChild<MAX_N_VALUE+1>
{
using type = Child<MAX_N_VALUE+1>;
static bool stop;
static void* castToConcrete(const DB& t, const Base* system)
{
return nullptr;
}
};
// Disactivate recursive behaviour for N = 11
bool findChild<MAX_N_VALUE+1>::stop = true;
// ------------------ App code
int main()
{
// Create objects database
DB db;
// --- Part 1: Application writers can't write generic-enough code
// Select (from compiled children) a new Base object with N = 2
// and register it to the DB
Base* b = Base::New(2, db);
b->update();
cout << "Access children by explicit dynamic_cast to Child<N>:" << endl;
// Get to the object through the objects DB.
// Child destructor should remove the object from DB too, nut meh again
const auto& oo = db.getObjectRef<Child<2>>("Child<2>");
cout << oo.test().size() << endl;
// --- Part 2: Application writers can write generic code if the compile
// Child<N> for their N
cout << "If Child<N> is polymorphic, we can access the correct child from findChild<0>:" << endl;
// Create a lambda that knows about db, which Base applies on itself
function<void(Base&)> lambda = [&db](Base& base) -> void {
// Cast and ignore the result
void* ptr = findChild<0>::castToConcrete(db, &base);
// Cast back to Child<0>
findChild<0>::type* c = static_cast<findChild<0>::type*>(ptr);
// Now access original Child<N> methods and members from Child<0>
cout << "Method:\n" << c->test().size() << endl;
cout << "Member:\n" << c->member.size() << endl;
};
b->execute(lambda);
return 0;
}
I compiled with GCC 9 with the following options:
-m64 -Wall -Wextra -Wno-unused-parameter -Wold-style-cast -Wnon-virtual-dtor -O0 -fdefault-inline -ftemplate-depth-200
It seems you want inheritance to group not so related classes...
std::variant (C++17) might be more appropriate:
template<int N>
class Child
{
// Member, N is not the size of matrix, more like the size of a component in matrix
Matrix<N> m_member;
public:
void update();
void execute(std::function<void(Matrix<N>&)> f) { f(m_member); }
};
using Base = std::variant<Child<2>, Child<3>>;
and then:
void foo(Base& obj)
{
struct Visitor {
template <std::size_t N>
void operator()(Child<N>& c) const
{
auto callable = [](Matrix<N>) -> void {/*..*/};
c.execute(callable);
}
} visitor;
std::visit(visitor, obj);
}
To answer to your Edit, whereas your callable take a Base, you might chain the dynamic_cast as follow:
template <int N>
void foo_base(Base& b)
{
if (auto* child = dynamic_cast<Child<N>*>(&b)) {
// Job with Child<N>
std::cout << "Method:" << child->test().size() << std::endl;
std::cout << "Member:" << child->member.size() << std::endl;
}
}
template <int... Ns>
void foo_dispatch(std::integer_sequence<int, Ns...>, Base& base)
{
//(foo_base<Ns>(base), ...); // C++17
const int dummy[] = {0, (foo_base<Ns>(base), 0)...};
static_cast<void>(dummy); // Avoid warning about unused variable
}
With a call similar to:
function<void(Base&)> lambda = [](Base& base) {
//foo_dispatch(std::integer_sequence<int, 2, 3>(), base);
foo_dispatch(std::make_integer_sequence<int, MAX_N_VALUE>(), base);
};
Demo
(std::integer_sequence is C++14, but can be implemented in C++11)
Note: Jarod's answer is still a little bit better if you know possible
values of N in Child<N> at compile-time and don't want to provide a way to extend them. Plus, of course, if you can use C++17.
Here I'm relying on "Similar types" defined by the standard as:
4.4 Qualification conversions [conv.equal]
... trimmed ...
Two pointer types T1 and T2 are similar if there exists a type T and integer n > 0 such that:
T1 is cv(1,0) pointer to cv(1,1) pointer to ··· cv(1,n−1) pointer to cv(1,n) T
and
T2 is cv(2,0) pointer to cv(2,1) pointer to ··· cv(2,n−1) pointer to (cv2,n) T
where each cv(i,j) is const, volatile, const volatile, or nothing
The same paragraph also shows the conditions for converting expressions.
In short, By inheriting from Base, all Child<N>* pointer types are similar to Base*, hence similar to each other.
Now, we know we can static_cast Child<N> to Child<0> without problems.
But is accessing Child<3> members from a Child<0>* safe?
3.10 Lvalues and rvalues [basic.lval]
If a program attempts to access the stored value of an object through a glvalue of other than one of the
following types the behavior is undefined:
the dynamic type of the object,
... trimmed ...
a type similar (as defined in 4.4) to the dynamic type of the object
There you have it, Accessing the values of Child<3> though a Child<0>* is in fact defined behavior.
This piece of code:
Base* b = Base::New(2);
b->update();
Child<2>* c1 = static_cast<Child<2>*>(b);
c1->update();
cout << c1->t.sValue << " " << c1->t.rValue << endl;
Child<0>* c2 = static_cast<Child<0>*>(b);
c2->update();
cout << c2->t.sValue << " " << c2->t.rValue << endl;
Will actually output (Note the value of the static variable Test<N>::sValue):
Calling Child<2>::update()
Calling Child<2>::update()
2 2
Calling Child<2>::update()
0 2
Static members will always point to Child<0>, and because of that,
Jarod's answer is a better solution for this problem.
But if one wants to allow expanding possible N values, this solution is OK; you just have to remember to put your static variables in Base and not in Child<N>.
Here is a minimal example, showing how to pass a lambda to the Base* while in fact the lambda, casts the pointer to Child<0> and operates on it:
https://onlinegdb.com/TTcMqOmWi
I would like to perform a down casting at execution time.
For what I read, if I want to do it, I need to compare the typeid of my polymorphic pointer with those of my derived classes, then do the casting in the correct type.
Plus, let's assume that I have a large number of derived classes.
This implies I have to write a long switch or list of if.
I would like to reduce this effort by using a list of classes to check.
This could look like:
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <map>
using namespace std;
class BaseShapes
{
virtual int run() = 0;
};
class ClassRectangle : public BaseShapes
{
int run()
{
std::cout << "I am a Rectangle. " << std::endl;
return 0;
}
float get_length () {return 12.4;};
float get_width() {return 6.2;};
};
class ClassCircle : public BaseShapes
{
int run()
{
std::cout << "I am a Cricle. " << std::endl;
return 0;
}
float get_diameter() {return 5.3;};
};
float function_only_for_Rectangle(ClassRectangle *rectangle)
{
// a function coming from a library that I cannot touch and that requires a derived type.
// But for the example I do something dummy!
return rectangle->get_length()
};
auto downcast_function (auto *p)
{
enum ListOfTypes {
ClassCircle,
ClassRectangle,
// and a lot more differents classes
};
for ( int fooInt = ClassCircle; fooInt < ClassRectangle; fooInt++ )
{
ListOfTypes fooItem = static_cast<ListOfTypes>(fooInt);
if (typeid(p) == typeid(fooItem))
{
auto pCasted =dynamic_cast<fooItem>(p);
return pCasted;
}
}
std::cout<< "downcast_function warning: no typeid is matching !" << std::endl;
return p;
};
int main(void)
{
// Beginning of main.
cout << "(Start)" << endl;
std::unique_ptr<BaseShapes> Shape1(new ClassRectangle());
auto p=Shape1.get();
//function_only_for_Rectangle(p); // not working since p is of type BaseShapes*
auto pbis=downcast_function(p); // should be of type ClassRectangle*
function_only_for_Rectangle(pbis);
// End of the main.
cout << "(End) " << endl;
return 0;
}
// EoF
So how can I write the downcast_function ? Or in other words, how can I iterate over a list of class types in order to make a typeid comparison and a casting ?
More details:
I agree that in this dummy example, I could simply override a function for each derived class and that is a much better way to deal with polymorphism. But I need to downcast, this is a constrain coming from a more complex problem where they are things that I am not allowed to changed. So, the question here is not why downcast but how.
To give a bit more details about my constrains are:
To start from a base pointer.
Get a derived pointer and give it to an external function (here called function_only_for_Rectangle, so I cannot modify this function).
I cannot do a simple and direct dynamic_cast<ClassRectangle>(p) because the type of p (or equivalently Shape1) will change at running time. This means that Shape1 can have "randomly" any derived type from BaseShapes. So I need something "automatic" and this is why I was thinking about iterate over all derived types and downcast according to the typeid match (but I am open to better ideas).
All the classes can modified if needed.
You say "polymorphic" but what you want to do is the opposite of it.
Instead of trying to work against polymorphism you could actually use it. If all subclasses have their own implementation of a virtual function then the caller does not need to care what the actual dynamic type of the object is. That is runtime polymorphism in a nutshell.
I suppose the naming for run is only for the example. Give it a better name, supply a default implementation in the base class, implement specific behavior in ClassRectangle and let the caller call it. No need to cast.
class BaseShapes
{
virtual int do_something_rectangly() { return 0;}
~virtual BaseShapes() = default;
};
class ClassRectangle : public BaseShapes
{
int do_something_rectangly() override
{
std::cout << "I am a Rectangle. " << std::endl;
return 0;
}
};
class ClassCircle : public BaseShapes
{
// does not override do_something_rectangly()
};
int function_for_any_base_shape(BaseShapes& s)
{
return s.do_something_rectangly();
};
int main(void)
{
// Beginning of main.
cout << "(Start)" << endl;
std::unique_ptr<BaseShapes> Rec1(new ClassRectangle());
function_for_any_base_shape(*pbis);
cout << "(End) " << endl;
return 0;
}
Concerning your edit:
I cannot do a simple and direct dynamic_cast(p) because the type of p (or equivalently Shape1) will change at running time. This means that Shape1 can have "randomly" any derived type from BaseShapes. [...]
Either I misunderstand what you wrote completely or you misunderstand how dynamic_cast works. dynamic_cast does already check what the dynamic type of the object is:
BaseShapes* b1 = new ClassCircle;
if(ClassRectangle* d = dynamic_cast<ClassRectangle*>(b1))
{
// cast is sucessfull
function_only_for_Rectangle(d);
} else {
// dynamic type of b1 is not ClassRectangle
}
To call function_only_for_Rectangle you do not need to be able to cast to all subtypes of ClassBase. You only need to dynamic_cast to a pointer to ClassRectangle and check if the cast was sucesfull.
I am trying to learn and write a self custom allocator - I was expecting that the cout statement should be printed but it never does - what is the wrong am I doing - how to write custom allocator:
#include <iostream>
#include <vector>
template < class T >
class MyAllocator : public std::allocator<T> {
public:
T* allocate(size_t size)
{
std::cout << "Allocation request size " << size << std::endl;
return new T[size];
}
};
int main()
{
std::vector <int, MyAllocator<int>> x;
x.push_back(10);
x.push_back(10);
x.push_back(10);
for (auto& var : x)
std::cout << "Value " << var << std::endl;
}
Output
Value 10
Value 10
Value 10
The inheritance of the standard allocator is not needed. Remove the inheritance : public std::allocator<T> and the compiler will be kind to inform you about what you missed to implement. Until C++17 the method construct must be implemented and it is used in std::vector, not allocate. Also value_type, deallocator and destroy are missing.
template< class U, class... Args >
void construct( U* p, Args&&... args );
Since you haven't implemented it and your allocator inherits the standard allocator, std::allocator::construct is called, that does not produce output.
Why you should not inherit std::allocator
The answer on this question is simple on the one hand and not simple in practice on the other hand.
Like other classes in C++ standard library, std::allocator does not have a virtual destructor, so it should not be inherited, if it is not explicitly indicated like in std::enable_shared_from_this.
Standard containers don't use class Allocator directly. They use std::allocator_traits. It helps to implement minimal user-defined allocators. If you implement only value_type, allocate and deallocate members of MyAllocator, std::allocator_traits<MyAllocator> makes MyAllocator fully conformed to C++ named requirements: Allocator.
Let look at your MyAllocator carefully. It inherits std::allocator and "replaces" std::allocator::allocate (2).
Let read std::allocator_traits::allocate (2) reference manual, that is called by std::vector:
Calls a.allocate(n, hint) if possible. If not possible (e.g. a has no two-argument member function allocate()), calls a.allocate(n).
What you have reached. You have implemented MyAllocator::allocate(std::size_t n) (2), but not MyAllocator::allocate(std::size_t n, const void* hint) (1), it is inherited from std::allocator. It is called from std::vector, that is not what you expected. If you had not inherited std::allocator, your implementation MyAllocator::allocate would be called.
You're half way there. As described here, the standard describes custom allocator classes having several optional and required named attributes and methods. If you want your example to work, at least you must implement the required ones. These are:
add a value_type.
add an allocate(n) method. Takes a size_t input and returns an address.
add a deallocate(p, n) method. Takes two inputs and has no output.
You must also remove the inheritance to std::allocator (see #S.M.'s answer). Example similar to your MyAllocator class:
#include <iostream>
#include <vector>
#include <cstdlib>
template < class T >
class MyAllocator
{
public:
T * allocate(size_t size)
{
std::cout << "Allocation request size => " << size << std::endl;
return new T[size];
}
void deallocate(T * p_t, size_t n)
{
std::free(p_t);
}
using value_type = T;
};
int main()
{
std::vector <int, MyAllocator<int>> x;
x.push_back(10);
x.push_back(10);
x.push_back(10);
for (auto& var : x)
std::cout << "Value " << var << std::endl;
}
Consider the following code:
#include <iostream>
#include <map>
class Value
{
public:
void set(const int intValue){ intValue_ = intValue; }
int read() const { return intValue_; }
void replaceIfInMap(){
std::map<int,int>::iterator it;
it = valuesToReplace_->find(intValue_);
if(it != valuesToReplace_->end()){
intValue_ = it->second;
}
}
Value(std::map<int,int>* valuesToReplace) : valuesToReplace_(valuesToReplace){}
private:
std::map<int,int>* valuesToReplace_;
int intValue_;
};
class Holder {
public:
void doStuffWithValues(){
Value a(&valuesToReplace_), b(&valuesToReplace_), c(&valuesToReplace_);
a.set(1); b.set(2); c.set(3);
valuesToReplace[2]=5;
a.replaceIfInMap(); b.replaceIfInMap(); c.replaceIfInMap();
std::cout << "a: " << a.read()
<< " b: " << b.read()
<< " c: " << c.read() << std::endl;
}
private:
std::map<int,int> valuesToReplace_;
};
int main()
{
Holder holder;
holder.doStuffWithValues();
}
How could I get access to the valuesToReplace_ member in a more convenient (and preferably more elegant) way? I have considered storing the map as a public static member of the class Value, but that would deny the possibility of having multiple instances of the Holder class, as each Holder instance requires a set of Value instances with different replacement settings.
A global map would be an even uglier "solution"...
Calling Value::read() from Holder and doing the map interaction there is not an option as this code is only a simplification and in the real code the equivalent of each instance of Value can store pointers to other instances of the same class rendering the aforementioned method overly complex and bulky.
Why does the above code even work? Holder::valuesToReplace_ is private! Is this just normal C++ behaviour (as you cannot get that pointer without access to the private members of the class anyway)?
Why does the above code even work? Holder::valuesToReplace_ is
private!
It is private, so Holder::doStuffWithValues can access it because it is a member function, nothing wrong there.
Value a(&valuesToReplace_), b(&valuesToReplace_), c(&valuesToReplace_);
a.set(1); b.set(2); c.set(3);
Here, all your Value objects have valuesToReplace_ pointing to the same map is that what you want? It seems strange, I would either have a static map (which would make a copy on assignment) or a smart pointer to prevent unexpected deletion (but allow NULL values).
How could I get access to the valuesToReplace_ member in a more
convenient (and preferably more elegant) way?
You could keep it private and have public member functions which return begin/end const_iterators for the map, or setIntForInt/getIntForInt accessor methods which are not dependent on internal implementation.
How about passing a reference to the valuesToReplace map to your replaceIfInMap method?
class Value
{
public:
void set(const int intValue){ intValue_ = intValue; }
int read() const { return intValue_; }
void replaceIfInMap(std::map<int,int> const& valuesToReplace_){
std::map<int,int>::const_iterator it;
it = valuesToReplace_->find(intValue_);
if(it != valuesToReplace_->end()){
intValue_ = it->second;
}
}
Value() {}
private:
int intValue_;
};
class Holder {
public:
void doStuffWithValues(){
Value a, b, c;
a.set(1); b.set(2); c.set(3);
valuesToReplace_[2]=5;
a.replaceIfInMap(valuesToReplace_);
b.replaceIfInMap(valuesToReplace_);
c.replaceIfInMap(valuesToReplace_);
std::cout << "a: " << a.read()
<< " b: " << b.read()
<< " c: " << c.read() << std::endl;
}
private:
std::map<int,int> valuesToReplace_;
};
What is the problem with this code ? this code is giving me lots of syntax errors. Also I would like to know why functors are used in C++.
class f
{
public:
int operator(int a) {return a;}
} obj;
int main()
{
cout << obj(0) << endl;
}
You're missing an extra pair of parenthesis when declaring operator(). The name of the function is operator(), and it still needs the list of parameters after it. Thus it should look like:
int operator()(int a) {return a;}
Function objects (a.k.a. functors) like this are typically used where you'd use a pointer to a function. However, they have the advantage that they can use inheritance and they encapsulate state as well. Often, well designed class or function templates will be able to use them almost interchangeably with function pointers. However, a good optimizer can typically produce better code when a template object is used.
For a fairly sophisticated example of how you might use function objects, have a look at expression templates.
Here's a small, somewhat contrived example of how they can use inheritance:
struct unary_int_func {
virtual int operator()(int i) = 0;
};
struct negate : public unary_int_func {
int operator()(int i) {return -i;}
};
struct one_plus : public unary_int_func {
int operator()(int i) {return i+1;}
};
void show_it(unary_int_func &op, int v) {
cout << op(v) << endl;
}
In this case, we create a base class with the operator as a pure virtual function. Then we derive to concrete classes that implement it. Code such as show_it() can then use any instance of a class derived from this base. While we could just have used a pointer to a function that takes an int and returns an int, this is more typesafe. Code that uses the function pointer would accept any such function pointer, whereas this way we can define a whole new hierarchy that maps an int to an int:
struct a_different_base_class {
virtual int operator()(int i) = 0;
};
but instances of this would not be interchangeable with instances of unary_int_func.
As for state, consider a running sum function:
struct running_sum : public unary_int_func {
int total;
running_sum() : total(0) {}
int operator()(int i) {return total += i;}
};
int main()
{
running_sum s;
cout << s(1) << endl;
cout << s(2) << endl;
cout << s(3) << endl;
cout << s(4) << endl;
}
Here, the instance of running_sum keeps track of the total. It will print out 1, 3, 6 and 10. Pointers to functions have no such way of keeping state between distinct invocations. SGI's STL page on function objects has a similar example to my running sum one, but shows how you can easily apply it to a range of elements in a container.
Functors are basically functions with states. Their biggest usage is in STL and Boost libraries. For example std::sort takes a type of functor called Comparator. In this context, perhaps a function object could have been passed instead but functor offers more flexibility by means of the data members you can have and manipulate with subsequent calls to the same functor. Functors are also used to implement C++ callbacks.
As you already have figured out the issue in your operator overloading code, I would rather try to address your doubt regarding functors.
Functor is a short for 'function pointer'.
These are widely used to provide a handle to customize the behavior of an algorithm, for example the sorting algorithms in STL use functor as parameter and the user (programmer) can implement the function to tell the algorithm the result of comparison for 2 elements.
because int operator(int) is effectively equal to int int #something_missing_here#(int)
operator is a reserved keyword and not qualifier as valid function identifier/name when used alone.
I would say it is used to make compiler understand that given expression are function declaration despite the invalid identifiers used (c++ only allow alphabet and underscore as first character in naming)
A functor is an object (instance of class or struct) that typically overloads the operator(). The difference between a functor and a normal function is that because a functor is an object, it can maintain state between calls.
Because a functor is an object, rules of inheritance apply as well and you can use this to your advantage.
A functor is also useful when you use the STL. std::sort, std::for_each, etc allow you to process the contents of an entire container (arrays included). Here's an example from cplusplus.com:
// for_each example
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
void myfunction (int i) {
cout << " " << i;
}
struct myclass {
void operator() (int i) {cout << " " << i;}
} myobject;
int main () {
vector<int> myvector;
myvector.push_back(10);
myvector.push_back(20);
myvector.push_back(30);
cout << "myvector contains:";
for_each (myvector.begin(), myvector.end(), myfunction);
// or:
cout << "\nmyvector contains:";
for_each (myvector.begin(), myvector.end(), myobject);
cout << endl;
return 0;
}
Try this:
class f
{
public:
int operator(int a) {return a;}
};
int main()
{
f obj;
cout<<obj(0)<<endl;
}