Showing posts with label General Utilities. Show all posts
Showing posts with label General Utilities. Show all posts

Friday, March 28, 2025

allocator_traits

Overview
This template supplies a uniform interface for allocator types.

Details
The allocator_traits class template provides the standardized way to access various properties of Allocators. The standard containers and other standard library components access allocators through this template, which makes it possible to use any class type as an allocator, as long as the user-provided specialization of std::allocator_traits implements all required functionality.

Syntax
The syntax is as below. 
template< class Alloc>
struct allocator_traits;

NameDescription
AllocThe allocator type, aliased as member type allocator_type.

Members
The default, non-specialized, std::allocator_traits contains the following members.
member typedefinition
allocator_typeAlloc
value_typeAlloc::value_type
pointerAlloc::pointer if present, otherwise value_type*
const_pointerAlloc::const_pointer if present, otherwise std::pointer_traits<pointer>::rebind<const value_type>
void_pointerAlloc::void_pointer if present, otherwise std::pointer_traits<pointer>::rebind<void>
const_void_pointerAlloc::const_void_pointer if present, otherwise std::pointer_traits<pointer>::rebind<const void>
difference_typeAlloc::difference_type if present, otherwise std::pointer_traits<pointer>::difference_type
size_typeAlloc::size_type if present, otherwise std::make_unsigned<difference_type>::type
propagate_on_container_copy_assignmentAlloc::propagate_on_container_copy_assignment if present, otherwise std::false_type
propagate_on_container_move_assignmentAlloc::propagate_on_container_move_assignment if present, otherwise std::false_type
propagate_on_container_swapAlloc::propagate_on_container_swap if present, otherwise std::false_type
is_always_equalAlloc::is_always_equal if present, otherwise std::is_empty<Alloc>::type

Member alias templates
These are defined on alias template.
member typedefinition
rebind_alloc<T>Alloc::rebind<T>::other if present, otherwise AllocTemplate<T,Args>
value_typeAlloc::value_type

Functionality
Methods
The following static methods are defined.
NameDescription
allocator_type 
allocator_traits::select_on_container_copy_construction
(const allocator_traits::& a)
If possible, obtains the copy-constructed version of the allocator a, by calling a.select_on_container_copy_construction(). If the above is not possible (e.g. Alloc does not have the member function select_on_container_copy_construction()), then returns a, unmodified.
  1. pointer allocator_traits::allocate
    (allocator_type& a, size_type n)
  2. pointer allocator_traits::allocate
    (allocator_type& a, size_type n, const void *  hint)
Uses the allocator a to allocate n * sizeof(value_type) bytes of uninitialized storage. An array of type value_type[n] is created in the storage, but none of its elements are constructed.
  1. Calls a.allocate(n).
  2. Additionally passes memory locality hint hint. Calls a.allocate(n, hint) if possible. If not possible (e.g. a has no two-argument member function allocate), calls a.allocate(n).
void allocator_traits::deallocate
(allocator_type& a, pointer p, size_type n)
Uses the allocator a to deallocate the storage referenced by p, by calling a.deallocate(p, n).
size_type allocator_traits::max_size
(allocator_type& a)
If possible, obtains the maximum theoretically possible allocation size from the allocator a, by calling a.max_size().
If the above is not possible (e.g., a does not have the member function max_size()), then returns std::numeric_limits<size_type>::max() / sizeof(value_type).
template< class U, class... Args >
void allocator_traits::construct
(allocator_type& a, U* p, Args&&... args )
Using allocator a, constructs an object of type T in allocated uninitialized storage pointed to by p, using
a.construct(p, std::forward<Args>(args)...)If it's not possible, global placement-new is used.
::new (static_cast<void*>(p)) T(std::forward<Args>(args)...).
template< class >
void allocator_traits::destroy
(allocator_type& a, U* p )
Calls the destructor of the object pointed to by p. If possible, does so by calling a.destroy(p). If not possible (e.g. a does not have the member function destroy()), then calls the destructor of *p directly, as p->~U().

The following Example 14 demonstrates usage of specialized allocator class that uses windows shared memory.


Thursday, March 27, 2025

allocator

Overview
Allocators are classes that define memory models to be used by some parts of the Standard Library, and most specifically, by STL containers.

Details
The allocator class template is the default Allocator used by all standard library containers if no user-specified allocator is provided. The default allocator is stateless, that is, all instances of the given allocator are interchangeable, compare equal and can deallocate memory allocated by any other instance of the same allocator type.

Syntax
The syntax is as below. 
template< class T>
class allocator;

//speciation
template<>
class allocator <void>;

NameDescription
TType of objects to be constructed on each element location.

Members
 It defines following types. The explicit specialization for void lacks the member typedefs reference, const_reference, size_type and difference_type. This specialization declares no member functions.
member typedefinition
value_typeElement type
pointerPointer to element
T*
const_pointerConst Pointer to element
const T*
referencereference to element
T&
const_referenceconst reference to element
const T&
size_typeQuantities of elements
size_t
difference_typeDifference between two pointers
ptrdiff_t
propagate_on_container_move_assignmenttrue_type
rebind<U>Its member type other is the equivalent allocator type to allocate elements of type Type.
template< class U >
struct rebind
{
    typedef allocator<U> other;
};
is_always_equaltrue_type

 Functionality
Constructors
NameDescription
  1. allocator()
  2. allocator (const allocator& alloc)
  3. template <class U>
    allocator (const allocator<U>& alloc)
Constructs the default allocator. Since the default allocator is stateless, the constructors have no visible effect.

Methods
NameDescription
  1. pointer address (reference x)
  2. const_pointer address (const_reference x)
 Returns the actual address of x even in presence of overloaded operator&.
pointer allocate
(size_type n, const void *  hint=0)
Attempts to allocate a block of storage with a size large enough to contain n elements of member type value_type (an alias of the allocator's template parameter), and returns a pointer to the first element.
The storage is aligned appropriately for objects of type value_type, but they are not constructed.
In the standard default allocator, the block of storage is allocated using ::operator new one or more times.
The pointer hint may be used to provide locality of reference: the allocator, if supported by the implementation, will attempt to allocate the new memory block as close as possible to hint.
void deallocate
(pointer p, size_type n)
Deallocates the storage referenced by the pointer p, which must be a pointer obtained by an earlier call to allocate().
The argument n must be equal to the first argument of the call to allocate() that originally produced p, otherwise, the behavior is undefined.
Calls ::operator delete(void*) 
The elements in the array are not destroyed by a call to this member function.
size_type max_size()
Returns the maximum theoretically possible value of n, for which the call allocate(n, 0) could succeed.
In most implementations, this returns
numeric_limits<size_type>::max() / sizeof(value_type). 
template< class U, class... Args >
void construct( U* p, Args&&... args )
Constructs an object of type T in allocated uninitialized storage pointed to by p, using global placement-new.
Calls ::new((void*)p) U(forward<Args>(args)...).
template< class U >
void destroy( U* p )
Calls the destructor of the object pointed to by p. Calls p->~U().

Non member Methods
NameDescription
template< class T1, class T2 >
bool operator==
(const allocator<T1>& lhs, const allocator<T2>& rhs ) 
Compares two default allocators. Since default allocators are stateless, two default allocators are always equal. Always returns true.
template< class T1, class T2 >
bool operator!=
(const allocator<T1>& lhs, const allocator<T2>& rhs ) 
Compares two default allocators. Since default allocators are stateless, two default allocators are always equal. Always returns false.

The following Example 13 demonstrates usage of allocator class.
    string numbers[] = {"one", "two", "three", "four"};
    size_t sz = sizeof(numbers);
    
    allocator<string> sal;
    auto sbuf = sal.allocate(sz);
    auto itr = sbuf;
    
    for (auto &s:numbers)
    {
        sal.construct(itr,s);
        ++itr;
    }

    //prints one two three four 
    for (itr = sbuf; itr != sbuf+sz; ++itr)
        cout << *itr  << " ";

    for (auto itr = sbuf; itr != sbuf+sz; ++itr)
       sal.destroy(itr);

    sal.deallocate(sbuf,sz);




Sunday, February 23, 2025

function

 
Overview
The function wrapper classes provide alternative to function pointers. It's basically a  general-purpose polymorphic function wrapper. 

Details
The function wrapper classes provide alternative to function pointers. It's basically a  general-purpose polymorphic function wrapper. Instances of function classes can store, copy, and invoke function pointers, lambda expressions, bind expressions, or other function objects, as well as pointers to member functions and pointers to data members.

The syntax is as shown below:
//generic type. 
//defined for specialization
template< typename T>
class function; /* undefined */

//R return type
//Args arguments
template< typename Ret, class... Args >
class function<R(Args...)>;

A decay copy of the wrapped callable object is stored internally by the object, which becomes the function's target member. The specific type of this target callable object is not needed in order to instantiate the function wrapper class; only its call signature.

function class objects can also be in a state with no target callable object. In this case they are known as empty functions, and calling them throws a bad_function_call exception.

constructors
Allocator based constructors are also available. 
NameDescription
function()
function (nullptr_t fn)
Default constructor with no target
function (const function & fn)Copy constructor. Copies target from fn to this.
function (Fn fn)The object stores a decayed copy of fn as its target.
Example
int square_fn(int x) {return x*x;}

// a function object class:
struct square_functor 
{
    int operator()(int x) {return x*x;}
};

// a class with data members:
struct square_struct 
{
    int x;
    int square() {return x*x;}
};


    //function
    function<int(int)> fn = square_fn;
    //returns 16
    fn(4);
    
    //pointer to function
    function<int(int)> fnptr = &square_fn;
    //returns 16
    fnptr(4);
    
    //function object
    function<int(int)> fnobj = square_functor();
    //returns 16
    fnobj(4);
    
    // lambda expression
    function<int(int)> fnlamb = [](int x){return x*x;};  
    //returns 16
    fnlamb(4);
    
    //predefined function object
    function<int(int,int)> fnmul = multiplies<int>();
    //returns 16
    fnlamb(4);
 
    // pointer to data member
    function<int&(square_struct&)> value = &square_struct::x;  
    // pointer to member function
    function<int(square_struct&)> sqr = &square_struct::square;  

    square_struct t {};

    //t.x=4
    value(t)=4;

    //returns 16
    sqr(t);

methods
NameDescription
operator bool()Returns whether the object is callable.i.e., if it has a callable object as target.

Example
    function<int(int,int)> fnmul;
    bool b =  static_cast<bool>(fnmul);
    
    fnmul = multiplies<int>();
    b =  static_cast<bool>(fnmul);
Ret operator()
(Args... args)
Calls the target callable object, forwarding args as arguments.

The effect depends on the type of the callable object targeted by the function object:

If the target is a function pointer or a function object, it is called forwarding the arguments to the call.
If the target is a pointer to a non-static member function, it is called using the first argument as the object on which the member is called (this may either be an object, a reference, or a pointer to it), and the remaining arguments are forwarded as arguments for the member function.
If it is a pointer to a non-static data member, it should be called with a single argument, and the function returns a reference to that member of its argument (the argument may either be an object, a reference, or a pointer to it).
If the object has no target (it is an empty function), it throws a bad_function_call exception.

Example
struct mul_struct 
{
    int x;
    int mul(int y) {return x*y;}
};

    square_struct a{10};
    function<int(square_struct&)> fnx = &square_struct::x;
    function<int(square_struct&,int)> fnmul = &square_struct::mul;
    //prints 10
    cout << fnx(a);
    //prints 100
    cout << fnmul(a,10);
TargetType* target()
Returns a pointer to the callable object stored in the function object.

Because function is a polymorphic wrapper class, it is unaware of the static type of its target callable object, and thus the template parameter TargetType must be explicitly specified.

TargetType shall match the target type, so that typeid(TargetType)==target_type(). Otherwise, the function always returns a null pointer.

Example
int add(int a,  int b){return a+b;}
int sub(int a,  int b){return a-b;}

function<int(int,int)> f = &add;
function<int(int,int)> f2 = plus<int>();

//returns 120
(*f.target<int(*)(int,int)>())(100,20) << endl;

//returns 120
(*f2.target<plus<int>>())(100,20);

*f.target<int(*)(int,int)>() = &sub;
//returns 80
f(100,20);
const type_info& target_type()Returns the type_info object that identifies the type of the target.

Example
function<int(int,int)> f = add;
function<int(int,int)> f2 = &add;
function<int(int,int)> f3 = plus<int>();

//int (__cdecl*)(int,int)
cout << f.target_type().name() << endl;
//int (__cdecl*)(int,int)
cout << f2.target_type().name() << endl;
//struct std::plus<int>
cout << f3.target_type().name() << endl;
The example 7 following lists the usage.

placeholder namespace
This namespace defines an unspecified number of objects: _1_2_3,..._N, where _N is implementation specific upper limit. 
syntax
namespace placeholders 
{  
	extern /* unspecified */ _1;  
	extern /* unspecified */ _2;  
	//....
	extern /* unspecified */ _N;  
}

These are used to specify placeholders in calls to function bind. When the function object returned by bind is called, an argument with placeholder::_1 is replaced by the first argument in the call, placeholder::_2 is replaced by the second argument in the call, and so on.

Example
void printnum(int n) {cout << n << endl;}
 
    auto pnum = bind(printnum,placeholders::_1);

    //prints 10
    pnum(10);

is_placeholder class
is_placeholder trait class can be used to check if the argument is a placeholder type or not.

syntax
template< class T >
struct is_placeholder;
If T is the type of a standard placeholder (_1, _2, _3, ...), then this template is derived from std::integral_constant<int, 1>, std::integral_constant<int, 2>, std::integral_constant<int, 3>, respectively.
If T is not a standard placeholder type, this template is derived from std::integral_constant<int, 0>.
bind uses is_placeholder to detect placeholders for unbound arguments.

Example
    //prints 1
    cout << is_placeholder<decltype(placeholders::_1)>::value << endl;
    //prints 2
    cout << is_placeholder<decltype(placeholders::_2)>::value << endl;
    //prints 0
    cout << is_placeholder<int>::value << endl;

mem_fn
Function template mem_fn generates wrapper objects for pointers to members, which can store, copy, and invoke a pointer to member. Both references and pointers (including smart pointers) to an object can be used when invoking a mem_fn.

syntax
template <class Ret, class T>  
/* unspecified */ mem_fn (Ret T::* pm);

Example
struct Msg
{
    char buf[50];
    void print(){cout << buf;};
} m;
 
    auto  pbuf = mem_fn(&Msg::buf);
    char str[] = "hello, world!";
    auto len = char_traits<char>::length(str);
    //sets m.buf to "hello, world"
    char_traits<char>::copy(pbuf(m),str,len);    

    auto  pprint = mem_fn(&Msg::print);
    //prints "hello, world"
pprint(m);
The example 10 demonstrates its usage.

bind
Returns a function object based on fn, but with its arguments bound to args.

syntax
template <class Fn, class... Args>  
/* unspecified */ bind (Fn&& fn, Args&&... args);

template <class Ret, class Fn, class... Args>  
/* unspecified */ bind (Fn&& fn, Args&&... args);
  • fn is a function object, pointer to function or pointer to member.
  • args is a list of arguments. Each argument may either be bound to a value or be a placeholder or a reference wrapper or another bind expression. If bound to a value, calling the returned function object will always use that value as argument otherwise the value passed in the call will be forwarded at runtime. 
  • ret A function object that, when called, calls fn with its arguments bound to args.
Example
struct Msg
{
    char buf[50];
    void print(){cout << buf;};
} m;


    char str[] = "hello, world!";
    auto len = char_traits<char>::length(str);
    //sets m.buf to "hello, world"
    auto pbuf = bind(&Msg::buf,placeholders::_1);
    char_traits<char>::copy(pbuf(m),str,len);

    //calls m.print();
    //prints hello, world
    auto pprint = bind(&Msg::print,placeholders::_1);
    pprint(m);

The example 11 following lists the usage:
 struct MyPair 
        {
            double a,b;
            double multiply() {return a*b;}
        } ten_two {10,2};
    
bind (divides<int>{},10,2)()						 = 5
bind (divides<int>{},placeholders::_1,2)(10)				 = 5
bind (divides<int>{},placeholders::_2,placeholders::_1)(10,2)		 = 0
bind<int> (divides<int>{},placeholders::_1,placeholders::_2)(10,3)	 = 3
bind (&MyPair::multiply,placeholders::_1)(ten_two)			 = 20
bind (&MyPair::a,ten_two)()						 = 10
The example 12 following lists the usage:
    void f(int n1, int n2, int n3, const int& n4, int n5);
        int g(int n1);
 
        struct Foo
        {
            void print_sum(int n1, int n2);
        int data = 10;
        } foo;
    
1) argument reordering and pass-by-reference: 
 bind(f, placeholders::_2, 42, placeholders::_1, cref(n), n)(1, 2, 1001) = 2 42 1 10 7

2) achieving the same effect using a lambda: 
[&ncref = n, n](auto a, auto b, auto /*unused*/)(1, 2, 1001) = 2 42 1 10 7

3) nested bind subexpressions share the placeholders: 
bind(f, placeholders::_3, bind(g, placeholders::_3), placeholders::_3, 4, 5)(10, 11, 12) = 12 12 12 4 5

4) bind a RNG with a distribution: 
bind(uniform_int_distribution<>(0, 10), default_random_engine{})() = 1
5) bind to a pointer to member function: 
bind(&Foo::print_sum, &foo, 95, placeholders::_1) = 100

6) bind to a mem_fn that is a pointer to member function: 
bind(mem_fn(&Foo::print_sum), &foo, 95, placeholders::_1) = 100

7) bind to a pointer to data member: 
bind(&Foo::data, placeholders::_1)(foo) = 10

8) bind to a mem_fn that is a pointer to data member: 
bind(mem_fn(&Foo::data), placeholders::_1)(foo) = 10

9) use smart pointers to call members of the referenced objects: 
bind(mem_fn(&Foo::data), placeholders::_1)(make_shared<Foo>(foo)) = 10
bind(mem_fn(&Foo::data), placeholders::_1)(make_unique<Foo>(foo)) = 10



Saturday, February 22, 2025

reference_wrapper

Overview
reference_wrapper is a class template that wraps a reference in a copyable, assignable object.

Details
reference_wrapper is a class template that wraps a reference in a copyable, assignable object.
It creates a wrapper around a reference to object or reference to function of type T. Instances of reference_wrapper are objects but they are implicitly convertible to T&, so that they can be used as arguments with the functions that take the underlying type by reference.
Helper functions ref and cref are often used to generate reference_wrapper objects.
reference_wrapper is used to pass objects by reference to bind, the constructor of thread, or the helper functions make_pair and make_tuple. It can also be used as a mechanism to store references inside standard containers (like vector) that cannot normally hold references.

The syntax is as shown below:
template <class T> class reference_wrapper;

constructors
Allocator based constructors are also available. 
NameDescription
reference_wrapper
(const reference_wrapper& x) 
Copy constructor.
reference_wrapper
 (T& ref)
The object stores a reference to ref.
Note that this constructor only accepts lvalues.
Example
int a(10),b(20),c(30);

// array of int&
reference_wrapper<int> refs[] = {a,b,c};
// vector of int&
vector<reference_wrapper<int>> vec {a,b,c};
//refs[0]=100 
//vec[0]=100
a=100;
The example 8 following lists the usage:

methods
NameDescription
reference_wrapper& operator=
(const reference_wrapper& rhs)
Copies the reference held by rhs, replacing the reference currently held in *this.
After the call, both rhs and *this refer to the same object or function.

Example
    int a,b;

    a=10; b=20;
    reference_wrapper<int> wrap1 (a);
    reference_wrapper<int> wrap2 (b);

    wrap1 = wrap2;
    ++wrap1; ++wrap2;

    //prints 10
    cout << "a: " << a << endl;
    //prints 22
    cout << "b: " << b << endl;


    a=10; b=20;
    int& ref1 (a);
    int& ref2 (b);

    ref1 = ref2;
    ++ref1; ++ref2;

    //prints 21
    cout << "a: " << a << endl;
    //prints 21
    cout << "b: " << b << endl;
T& get()
Returns a reference to the referred element.

Example
int a(10),b(20),c(30);

// array of int&
reference_wrapper<int> refs[] = {a,b,c};
// vector of int&
vector<reference_wrapper<int>> vec {a,b,c};
//a=100 
//vec[0]=100
refs[0].get()=100;
operator type&()
Returns a reference to the referred element.This returns the same as member get.

Example
int a(10),b(20),c(30);

// array of int&
reference_wrapper<int> refs[] = {a,b,c};

// vector of int&
vector<reference_wrapper<int>> vec {a,b,c};

//a=100 
//vec[0]=100
static_cast<int&>(refs[0])=100;
template<class... ArgTypes >
typename result_of<T&(ArgTypes&&...)>::type
operator() ( ArgTypes&&... args )
Accesses the referred element.
If type is a function or a function object type, it is called forwarding the arguments to the function.
If type is a pointer to a non-static member function, it is called using the first argument as the object on which the member is called, and the remaining arguments are forwarded as arguments for the function.
If type is a pointer to a non-static data member, it should be called with a single argument, and the function returns a reference to that member of its argument.

Example
void printnum(int n) {cout << n << endl;}
    auto  fp = ref(printnum);
   //prints 10
    fp(10);

ref
A helper function that constructs an object of the appropriate reference_wrapper type to hold a reference to elem.
Syntax
//creates a new reference_wrapper of type T&
template <class T> 
reference_wrapper<T> ref (T& elem);

//creates a copy of reference_wrapper from x  of type T&
template <class T> 
reference_wrapper<T> ref (reference_wrapper<T>& x);

Example
struct Msg
{
    char buf[50];
    void print(){cout << buf;};
} m;

    char  (Msg::*mbuf)[50] = &Msg::buf;
    auto pbuf = ref(mbuf);
    
    void (Msg::*mprint)() = &Msg::print;
    auto pprint = ref(mprint);

    char str[] = "hello, world!";
    auto len = char_traits<char>::length(str);
    //sets m.buf to "hello, world"
    char_traits<char>::copy(pbuf(&m),str,len);

    //calls m.print();
    //prints hello, world
    pprint(m);

cref
A helper function that constructs an object of the appropriate reference_wrapper type to hold a const reference to elem.
Syntax
//creates a new reference_wrapper of type const T&
template <class T> 
reference_wrapper<const T> ref (const T& elem);

//creates a copy of reference_wrapper from x of type const T& 
template <class T> 
reference_wrapper<const T> ref (reference_wrapper<T>& x);

Example
void f(int& n1, int& n2, const int& n3)
{
    //prints In function: 1 11 12
    cout << "In function: " << n1 << ' ' << n2 << ' ' << n3 << endl;
    ++n1; // increments the copy of n1 stored in the function object
    ++n2; // increments the main()'s n2
    // ++n3; // compile error
}
 
    int n1 = 1, n2 = 2, n3 = 3;
    function<void()> bound_f = bind(f, n1, ref(n2), cref(n3));
    n1 = 10;
    n2 = 11;
    n3 = 12;
    //prints Before function: 10 11 12
    cout << "Before function: " << n1 << ' ' << n2 << ' ' << n3 << endl;
    bound_f();
    //prints After function: 10 12 12
    cout << "After function: " << n1 << ' ' << n2 << ' ' << n3 << endl;

The example 9 following lists the usage of ref and cref classes.