Custom allocator method is not called - c++

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;
}

Related

Array of polymorphic objects

I commonly come across the need to create arrays or vectors of polymorphic objects. I'd usually prefer to use references, rather than smart pointers, to the base class because they tend to be simpler.
Arrays and vectors are forbidden from containing raw references, and so I've tended to use smart pointers to the base classes instead. However, there is also the option to use std::reference_wrapper instead: https://en.cppreference.com/w/cpp/utility/functional/reference_wrapper
From what I can tell from the documentation, this is what one of its intended uses is, but when the topic of arrays containing polymorphic objects comes up, the common advice seems to be to use smart pointers rather than std::reference_wrapper.
My only thought is that smart pointers may be able to handle the lifetime of the object a little neater?
TL:DR; Why are smart pointers, such as std::unique_ptr seemingly preferred over std::reference_wrapper when creating arrays of polymorphic objects?
In very simple terms:
unique_ptr is the owner of the object. It manages the lifetime of the owned object
reference_wrapper wraps a pointer to an object in memory. It does NOT manage the lifetime of the wrapped object
You should create an array of unique_ptr (or shared_ptr) to guarantee the release of the object when it's not needed anymore.
If you are sufficiently motiviated, you can write a poly_any<Base> type.
A poly_any<Base> is an any restricted to only storing objects that derive from Base, and provides a .base() method that returns a Base& to the underlying object.
A very incomplete sketch:
template<class Base>
struct poly_any:private std::any
{
using std::any::reset;
using std::any::has_value;
using std::any::type;
poly_any( poly_any const& ) = default;
poly_any& operator=( poly_any const& ) = default;
Base& base() { return get_base(*this); }
Base const& base() const { return const_cast<Base const&>(get_base(const_cast<poly_any&>(*this))); }
template< class ValueType,
std::enable_if_t< /* todo */, bool > =true
>
poly_any( ValueType&& value ); // todo
// TODO: sfinae on ValueType?
template< class ValueType, class... Args >
explicit poly_any( std::in_place_type_t<ValueType>, Args&&... args ); // todo
// TODO: sfinae on ValueType?
template< class ValueType, class U, class... Args >
explicit poly_any( std::in_place_type_t<ValueType>, std::initializer_list<U> il,
Args&&... args ); // todo
void swap( poly_any& other ) {
static_cast<std::any&>(*this).swap(other);
std::swap( get_base, other.get_base );
}
poly_any( poly_any&& o ); // todo
poly_any& operator=( poly_any&& o ); // todo
template<class ValueType, class...Ts>
std::decay_t<ValueType>& emplace( Ts&&... ); // todo
template<class ValueType, class U, class...Ts>
std::decay_t<ValueType>& emplace( std::initializer_list<U>, Ts&&... ); // todo
private:
using to_base = Base&(*)(std::any&);
to_base get_base = 0;
};
Then you just have to intercept every means of putting stuff into the poly_any<Base> and store a get_base function pointer:
template<class Base, class Derived>
auto any_to_base = +[](std::any& in)->Base& {
return std::any_cast<Derived&>(in);
};
Once you have done this, you can create a std::vector<poly_any<Base>> and it is a vector of value types that are polymorphically descended from Base.
Note that std::any usually uses the small buffer optimization to store small objects internally, and larger objects on the heap. But that is an implementation detail.
Basically, a reference_wrapper is a mutable reference: Like a reference, it must not be null; but like a pointer, you can assign to it during its lifetime to point to another object.
However, like both pointers and references, reference_wrapper does not manage the lifetime of the object. That's what we use vector<uniq_ptr<>> and vector<shared_ptr<>> for: To ensure that the referenced objects are properly disposed off.
From a performance perspective, vector<reference_wrapper<T>> should be just as fast and memory efficient as vector<T*>. But both of these pointers/references may become dangling as they are not managing object lifetime.
Let's try the experiment:
#include <iostream>
#include <vector>
#include <memory>
#include <functional>
class Base {
public:
Base() {
std::cout << "Base::Base()" << std::endl;
}
virtual ~Base() {
std::cout << "Base::~Base()" << std::endl;
}
};
class Derived: public Base {
public:
Derived() {
std::cout << "Derived::Derived()" << std::endl;
}
virtual ~Derived() {
std::cout << "Derived::~Derived()" << std::endl;
}
};
typedef std::vector<std::reference_wrapper<Base> > vector_ref;
typedef std::vector<std::shared_ptr<Base> > vector_shared;
typedef std::vector<std::unique_ptr<Base> > vector_unique;
void fill_ref(vector_ref &v) {
Derived d;
v.push_back(d);
}
void fill_shared(vector_shared &v) {
std::shared_ptr<Derived> d=std::make_shared<Derived>();
v.push_back(d);
}
void fill_unique(vector_unique &v) {
std::unique_ptr<Derived> d(new Derived());
v.push_back(std::move(d));
}
int main(int argc,char **argv) {
for(int i=1;i<argc;i++) {
if(std::string(argv[i])=="ref") {
std::cout << "vector" << std::endl;
vector_ref v;
fill_ref(v);
std::cout << "~vector" << std::endl;
} else if (std::string(argv[i])=="shared") {
std::cout << "vector" << std::endl;
vector_shared v;
fill_shared(v);
std::cout << "~vector" << std::endl;
} else if (std::string(argv[i])=="unique") {
std::cout << "vector" << std::endl;
vector_unique v;
fill_unique(v);
std::cout << "~vector" << std::endl;
}
}
}
running with argument shared:
vector
Base::Base()
Derived::Derived()
~vector
Derived::~Derived()
Base::~Base()
running with argument unique
vector
Base::Base()
Derived::Derived()
~vector
Derived::~Derived()
Base::~Base()
running with argument ref
vector
Base::Base()
Derived::Derived()
Derived::~Derived()
Base::~Base()
~vector
Explanation:
shared: Memory is shared by different parts of the code. In the example, the Derived object is first owned by the d local var in the function fill_shared() and by the vector. When the code exits the scope of the function object is still owned by the vector and only when the vector goes finally away, the object is deleted
unique: Memory is owned by the unique_ptr. In the example, the Derived object is first owned by the d local var. However it must be moved into the vector, transferring the ownership. Same as before, when the only owner goes away, the object gets deleted.
ref: There's no owning semantics. The object is created as a local variable of the fill_ref() function, and the reference to the object can be added to the vector. However, the vector does not own the memory and when the code goes out of the fill_ref() function, the object goes away, leaving the vector pointing to unallocated memory.

Custom deallocator with an std::vector doesn't get called

I am expecting this code to print "Hello world" - "Hello " when the memory is deallocated and "world" in main. However "Hello" never gets printed, meaning that my deallocator doesn't get called. What's the proper way to implement it?
#include <iostream>
#include <vector>
class MyAllocator : public std::allocator<uint8_t>
{
public:
void deallocate(uint8_t* data, std::size_t size)
{
std::cout << "Hello ";
std::allocator<uint8_t>::deallocate(data, size);
}
};
int main()
{
{
std::vector<uint8_t, MyAllocator> v(100);
}
std::cout << "world\n";
return 0;
}
I assume it just calls the default std::allocator<uint8_t>::deallocate() function, but I am not seeing a way to prevent it and make it call my function.
In fact your allocator will work if you define rebind:
#include <iostream>
#include <vector>
class MyAllocator : public std::allocator<uint8_t>
{
public:
template <typename U>
struct rebind
{
typedef MyAllocator other;
};
void deallocate(uint8_t* data, std::size_t size)
{
std::cout << "Hello ";
std::allocator<uint8_t>::deallocate(data, size);
}
};
int main()
{
{
std::vector<uint8_t, MyAllocator> v(100);
}
std::cout << "world\n";
return 0;
}
Produces:
Hello world
std::allocator defines the member template rebind<U>.
And std::vector properly uses it to make sure it allocates the right chunks of memory, with the appropriate size and alignment, so even though you passed your custom allocator, the rebinding results in actually using the standard allocator.
See for example http://en.cppreference.com/w/cpp/concept/Allocator for the potential members of an allocator.

Correctly Writing a Range Based Constructor

I had a question to do with writing a range based constructor for a class but couldn't find the right phrasing to search for help on google.
Suppose I am writing a simple class, like vector, which involves having a range based constructor that inserts elements from the range into the current container:
// foo.h
#ifndef FOO_H
#define FOO_H
#include <iostream>
class Foo {
public:
Foo() {
std::cout << "Default constructor called" << std::endl;
}
template<class InputIterator> Foo(InputIterator first, InputIterator last) {
std::cout << "Range based constructor called" << std::endl;
}
Foo(size_t n, int val) {
std::cout << "size_t, int constructor called" << std::endl;
}
};
#endif // FOO_H
and have a cpp file
#include <iostream>
#include <vector>
#include "foo.h"
using std::cout; using std::endl;
int main() {
std::vector<int> v(10, 5);
Foo f_default;
Foo f_range(v.begin(), v.end());
Foo f_int(314, 159); // want this to call size_t, int ctctr
return 0;
}
In the third line in main, we create a Foo f_int(314, 159) which intuitively we want to call the size_t, int constructor. However it is matching the generic template constructor for ranges instead. Is there a way issues like this are addressed in C++? I feel like I am incorrectly dealing with writing range based constructors.
I can imagine you can use template specialization maybe, but don't really see how.
An example where such a situation might happen is if we are writing a vector class where there is a constructor based on a size_t and default value (which would be templatised on the class but I simplified here) and another constructor based on iterator ranges.
The constructor template is a better match in the third case because you're passing two int arguments, while the Foo(size_t n, int val) requires an int to size_t conversion for the first argument. If you modify your code to
Foo f_int(static_cast<size_t>(314), 159);
the constructor you want is called. But of course, this is not a good solution because it's easy to accidentally call the wrong constructor. Instead, you can use SFINAE to drop the constructor template from the overload resolution set by ensuring the argument types are iterators.
template<class InputIterator,
class = std::enable_if_t<
std::is_base_of<
std::input_iterator_tag,
typename std::iterator_traits<InputIterator>::iterator_category
>{}
>
>
Foo(InputIterator first, InputIterator last) {
std::cout << "Range based constructor called" << std::endl;
}
If you look at the table here, all iterators you can read from are InputIterators or derived types. So the code above is checking that the InputIterator type being passed to the constructor is of that type or something derived from that type.

Can I Have Polymorphic Containers With Value Semantics in C++11?

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.

Problem with operator overloading

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;
}