<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://parikagoel.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://parikagoel.github.io/" rel="alternate" type="text/html" /><updated>2026-02-20T11:17:25+00:00</updated><id>https://parikagoel.github.io/feed.xml</id><title type="html">My C++ Diary</title><subtitle>This website started as an attempt to put all the cool stuff I read or use in C++ at one place</subtitle><author><name>Parika Goel</name></author><entry><title type="html">Multithreading in C++</title><link href="https://parikagoel.github.io/2024/01/06/cpp-multithreading.html" rel="alternate" type="text/html" title="Multithreading in C++" /><published>2024-01-06T00:00:00+00:00</published><updated>2024-01-06T00:00:00+00:00</updated><id>https://parikagoel.github.io/2024/01/06/cpp-multithreading</id><content type="html" xml:base="https://parikagoel.github.io/2024/01/06/cpp-multithreading.html"><![CDATA[<h3 id="threads">Threads</h3>

<h3 id="mutex-mutual-exclusion">Mutex (Mutual Exclusion)</h3>
<p>Avoiding race condition
Way to synchronize access to critical section</p>

<h3 id="semaphores">Semaphores</h3>

<h3 id="locks">Locks</h3>
<p>RAII wrappers over mutexes <br />
std::lock_guard</p>

<p>std::unique_lock - mutex ownership wrapper allowing deferred locking, time-constrained attempts at locking, recursive locking, transfer of lock ownership and use with condition variables</p>

<p>std::scoped_lock - deadlock avoiding RAII wrapper for multiple mutexes</p>

<p>std::lock - locks specified (can be more than one) mutexes, blocks if they are unavailable</p>

<p>Reader-writer locks, Shared mutex, shared lock</p>

<h3 id="thread-synchronization--communication">Thread Synchronization / Communication</h3>
<h4 id="condition-variables">Condition Variables</h4>
<h4 id="promise-future">Promise-Future</h4>

<h3 id="stdasync">std::async</h3>
<p><a href="2024-01-04-cpp-async.md">Asynchronous Function calls</a></p>

<h3 id="stdpackaged_task">std::packaged_task</h3>]]></content><author><name>Parika Goel</name></author><category term="Other" /><summary type="html"><![CDATA[Threads]]></summary></entry><entry><title type="html">Asynchronous Function Calls (std::async)</title><link href="https://parikagoel.github.io/2024/01/04/cpp-async.html" rel="alternate" type="text/html" title="Asynchronous Function Calls (std::async)" /><published>2024-01-04T00:00:00+00:00</published><updated>2024-01-04T00:00:00+00:00</updated><id>https://parikagoel.github.io/2024/01/04/cpp-async</id><content type="html" xml:base="https://parikagoel.github.io/2024/01/04/cpp-async.html"><![CDATA[<p>std::async is a way to achieve thread communication. It takes a callable object as an argument. Under the hood, async uses promise-future interface. A promise object is created which executes the callable object and a future object is returned. The returned future can be used to retrieve the result at a later point in time.</p>

<p>std::async can take any callable object as argument. Below code snippet shows usage with a function, function object and a lambda.</p>

<pre><code>#include &lt;iostream&gt;
#include &lt;future&gt;
#include &lt;string&gt;

std::string callableFunc(const std::string&amp; str)
{
    return str + " returned from function.\n";
}

struct CallableFuncObj{
    std::string operator()(const std::string&amp; str) const
    {
        return str + " returned from function struct.\n";
    }
};

int main()
{
    std::string hw = "Hello World ";
    CallableFuncObj funcObj;
    auto funcFut = std::async(callableFunc, hw);
    auto funcStrFut = std::async(funcObj, hw);
    auto lambdaFut = std::async([](const std::string&amp; str){ return str + " returned from lambda.\n";}, hw);

    std::cout &lt;&lt; funcFut.get();
    std::cout &lt;&lt; funcStrFut.get();
    std::cout &lt;&lt; lambdaFut.get();

    return 0;
}

</code></pre>

<h3 id="concurrent-or-deferred-execution">Concurrent or Deferred Execution</h3>

<p>The callable object can be executed at the moment the call to async is made or can be deferred to a later point in time by passing an extra argument to the async call.</p>

<p>std::launch::async - It tells the compiler to launch a separate thread to execute the callable object and execute it immediately.</p>

<p>std::launch::deferred - It tells the compiler to perform the execution of callable object in the same thread and delay it to the point when the result is asked for.</p>

<table>
  <tbody>
    <tr>
      <td>Default value for this parameter is std::launch::async</td>
      <td>std::launch::deferred, which means the compiler can decide which one to pick.</td>
    </tr>
  </tbody>
</table>

<p>Concurrent Execution: <br />
In the example below, the function gets executed even before the get call to future is made. And it can also been seen that it is executed in separate thread.</p>

<p>Deferred Execution: <br />
In the example below, the function gets executed when the get call to future is made. And it can also been seen that it is executed in same thread.</p>

<pre><code>std::string callableFunc(const std::string&amp; str)
{
    std::cout &lt;&lt; "Function thread: " &lt;&lt; std::this_thread::get_id() &lt;&lt; "\n";
    return str + " returned from function.\n";
}

int main()
{
    std::string hw = "Hello World ";
    std::cout &lt;&lt; "Main thread: " &lt;&lt; std::this_thread::get_id() &lt;&lt; "\n";
    auto funcFut = std::async(std::launch::async, callableFunc, hw);
    //auto funcFut = std::async(std::launch::deferred, callableFunc, hw);
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::cout &lt;&lt; "Get value from future\n";
    std::cout &lt;&lt; funcFut.get() &lt;&lt; "\n";

    return 0;
}

Output for std::launch::async- 
Main thread: 140640628083456
Function thread: 140640620901952
Get value from future
Hello World  returned from function.

Output for std::launch::deferred- 
Main thread: 140249498356480
Get value from future
Function thread: 140249498356480
Hello World  returned from function.
</code></pre>]]></content><author><name>Parika Goel</name></author><category term="Other" /><summary type="html"><![CDATA[std::async is a way to achieve thread communication. It takes a callable object as an argument. Under the hood, async uses promise-future interface. A promise object is created which executes the callable object and a future object is returned. The returned future can be used to retrieve the result at a later point in time.]]></summary></entry><entry><title type="html">Concepts</title><link href="https://parikagoel.github.io/2023/11/24/cpp-concepts.html" rel="alternate" type="text/html" title="Concepts" /><published>2023-11-24T00:00:00+00:00</published><updated>2023-11-24T00:00:00+00:00</updated><id>https://parikagoel.github.io/2023/11/24/cpp-concepts</id><content type="html" xml:base="https://parikagoel.github.io/2023/11/24/cpp-concepts.html"><![CDATA[<p>Concepts are a mechanism to put constraints on template type parameters
For example if we want our templated function to only be called with an int, we can use concepts
and it will give compiler error in case any other data type is used. <br />
To use concepts, include “concepts” header file in your program.</p>

<p>The functionality provided by concepts can be achieved using static_assert and type_traits as well. For example, we can put constraint on template parameters in following way:</p>

<pre><code>template &lt;typename T&gt;
void print_number(T n)
{
    static_assert(std::is_integral_v, "Must pass an integral value");
    std::cout &lt;&lt; "n: " &lt;&lt; n &lt;&lt; "\n";
}
</code></pre>

<p>Concepts provide a more neater and readable way to add these constraints.</p>

<h3 id="adding-concept-to-function-template">Adding concept to function template</h3>
<p>Example using built-in concepts</p>

<pre><code>template &lt;typename T&gt;
requires std::integral&lt;T&gt;
T sum(T a, T b)
{
    return a+b;
}

int a0 = 10;
int a1 = 20;
std::cout &lt;&lt; sum(a0,a1) &lt;&lt; "\n"; // 30

double b0 = 1.3;
double b1 = 2.6;
std::cout &lt;&lt; sum(a0,a1) &lt;&lt; "\n"; // Compiler Error: integral concept is not satisfied
</code></pre>

<p>Below are two other way/syntax to write the same concept</p>
<pre><code>template &lt;std::integral T&gt;
T sum(T a, T b)
{
    return a+b;
}

auto add(std::integral auto a, std::integral auto b)
{
    return a + b;
}

template &lt;typename T&gt;
T add (T a, T b) -&gt; requires std::integral&lt;T&gt;
{
    return a + b;
}
</code></pre>

<h3 id="custom-concepts">Custom Concepts</h3>

<p>Different ways to write custom concepts</p>

<pre><code>template &lt;typename T&gt;
concept MyIntegral = std::is_integral_v&lt;T&gt;;

template &lt;typename T&gt;
concept Multipliable = requires(T a, T b){
    a * b;
};

template &lt;typename T&gt;
concept Incrementable = requires(T a){
    // it makes sure that below three statements are valid syntax
    // for the template parameter type T
    // e.g. int would be ok but string would fail
    a+=1;
    a++;
    ++a;
};
</code></pre>

<p>Once our custom concepts have been created, they can be used in the same way as we used built-in concepts
Example Below:</p>

<pre><code>#include &lt;concepts&gt;
#include &lt;iostream&gt;
#include &lt;type_traits&gt;
#include &lt;string&gt;

template &lt;typename T&gt;
concept Incrementable = requires (T a){
    a+=1;
    a++;
    ++a;
};

template &lt;typename T&gt;
requires Incrementable&lt;T&gt; 
T add(T a, T b)
{
    return a + b;
}

int main()
{
    int a{1};
    int b{19};
    std::cout &lt;&lt; add(a,b) &lt;&lt; "\n"; // 20

    std::string c{"Hello"};
    std::string d{"World"};
    //std::cout &lt;&lt; add(c,d) &lt;&lt; "\n"; // Compiler Error
    return 0;
}
</code></pre>]]></content><author><name>Parika Goel</name></author><category term="Other" /><summary type="html"><![CDATA[Concepts are a mechanism to put constraints on template type parameters For example if we want our templated function to only be called with an int, we can use concepts and it will give compiler error in case any other data type is used. To use concepts, include “concepts” header file in your program.]]></summary></entry><entry><title type="html">C++ Lambda Functions</title><link href="https://parikagoel.github.io/2022/03/28/cpp-lambdas.html" rel="alternate" type="text/html" title="C++ Lambda Functions" /><published>2022-03-28T00:00:00+00:00</published><updated>2022-03-28T00:00:00+00:00</updated><id>https://parikagoel.github.io/2022/03/28/cpp-lambdas</id><content type="html" xml:base="https://parikagoel.github.io/2022/03/28/cpp-lambdas.html"><![CDATA[<h3 id="introduction">Introduction</h3>

<p>Lambda functions are inline functions that are designed to be used for small code which will not be reused and thus is not worth naming.</p>

<p>The basic syntax of lambda functions is as below:</p>

<pre><code>[capture clause] (parameters) -&gt; return type
{
  function body
}
</code></pre>

<h3 id="capture-clause">Capture Clause</h3>
<p>Lambda functions can capture the variables from the enclosing scope. By capture, we mean if a particular variable can be used inside a lambda function.</p>

<p>The variables can be captured in three ways:</p>
<ul>
  <li>Capture by reference
    <ul>
      <li>[&amp;] -&gt; All the variables from the enclosing scope will be captured by reference.</li>
      <li>[&amp;a] -&gt; Instead of capturing all the variables, one specific variable a can also be captured by reference. Then no other variable will be accessible inside
the lambda function.</li>
    </ul>
  </li>
  <li>Capture by value
    <ul>
      <li>[=] -&gt; All the variables from the enclosing scope will be captured by value.</li>
      <li>[a] -&gt; Instead of capturing all the variables, one specific variable a can also be captured by value. Then no other variable will be accessible inside
the lambda function.</li>
    </ul>
  </li>
  <li>Mixed capture
    <ul>
      <li>The above two mentioned captures can be used in any possible combination.</li>
      <li>[a,&amp;b] -&gt; Variable a is captured by value, variable b is captured by reference.</li>
      <li>[=,&amp;b] -&gt; Variable b is captured by reference. All other variables are captured by value.</li>
    </ul>
  </li>
</ul>

<p>An empty [] means that no variable from enclosing scope is accessible inside the lambda body.</p>

<h3 id="return-type">Return Type</h3>
<p>It is optional to specify the return type of the function. The compiler can deduce automatically what would be the return type. But in some complex cases, it might
be helpful to specify it explicitly.</p>

<h3 id="example">Example</h3>

<p>The code below shows a simple example of lambda usage. A number defined by variable ‘noToAdd’ is added to each entry in a vector.</p>

<pre><code>#include &lt;algorithm&gt;
#include &lt;vector&gt;

int main()
{
	int noToAdd = 8;
	std::vector&lt;int&gt; vecOfNums{3,2,7,8,4,6};

	// noToAdd captured by reference
	std::for_each(vecOfNums.begin(), vecOfNums.end(), [&amp;noToAdd](int num) {return num + noToAdd; });

	// noToAdd captured by value
	std::for_each(vecOfNums.begin(), vecOfNums.end(), [noToAdd](int num) {return num + noToAdd; });
	return 0;
}

</code></pre>

<h3 id="capture-member-variable-or-this-pointer-in-lambda">Capture Member Variable or This pointer in Lambda</h3>

<p>Member Variables can be captured by value and reference inside the member functions as shown in the example below:</p>

<pre><code>class Test{
  public:
    Test(): _data(50){}
    void print()
    {
      [=](){ std::cout &lt;&lt; _data &lt;&lt; "\n"}();
    }
  private:
    int _data;
};
</code></pre>

<h4 id="capturing-this-pointer">Capturing This pointer</h4>

<p>Since C++11, this pointer could only be captured by reference. Usage of both [=] and [&amp;] implicitly captures this by reference. This leads to problems when the object is temporary or goes out of scope leading to dangling reference.</p>

<pre><code>struct Example{
  int m_x = 0;

  void func()
  {
    // m_x by ref, implicitly captures this by ref 
    [&amp;](){};

    // m_x by ref, explicilty captures this by ref
    // redundant 
    [&amp;, this](){};

    // m_x by value, implicitly captures this by ref 
    [=](){};

    // error: not allowed
    [=, this](){};
  }

};
</code></pre>

<p>Value capture of this pointer was added in C++17 to avoid above mentioned problems. This means lambda gets its own copy of <em>this, allowing modifications without affecting the original object. Since C++17, use of [this] captures this by reference and use of [</em>this] captures this by value.</p>]]></content><author><name>Parika Goel</name></author><category term="Other" /><summary type="html"><![CDATA[Introduction]]></summary></entry><entry><title type="html">C++ Maps</title><link href="https://parikagoel.github.io/2022/03/22/cpp-maps.html" rel="alternate" type="text/html" title="C++ Maps" /><published>2022-03-22T00:00:00+00:00</published><updated>2022-03-22T00:00:00+00:00</updated><id>https://parikagoel.github.io/2022/03/22/cpp-maps</id><content type="html" xml:base="https://parikagoel.github.io/2022/03/22/cpp-maps.html"><![CDATA[<h3 id="ordered-vs-unordered-maps">Ordered vs Unordered Maps</h3>

<p>C++ STL provides <strong><em>std::map</em></strong> container which maps a key to a value and maintains the key in an ordered fashion. Another STL container <strong><em>std::unordered_map</em></strong> also maps a key to a value but no ordering is maintained. Two values can not have the same key in both containers.</p>

<p>Below code shows the difference between the two. In the case of ordered map, the order of the keys is maintained irrespective of the order in which they are entered.</p>

<pre><code>#include &lt;iostream&gt;
#include &lt;map&gt;
#include &lt;unordered_map&gt;

int main()
{
	std::map&lt;std::string, std::string&gt; empRecords;

	// insert an entry
	empRecords.insert({ "MAR", "Maria" });
	empRecords["CHR"] = "Christoph";
	empRecords.insert(std::make_pair("SEB", "Sebastian"));

	std::cout &lt;&lt; "Employee Records using Ordered Map\n";
	for (const auto&amp; [key, val] : empRecords)
		std::cout &lt;&lt; "Emp Code: " &lt;&lt; key &lt;&lt; " , Emp Name: " &lt;&lt; val &lt;&lt; std::endl;

	std::cout &lt;&lt; std::endl &lt;&lt; std::endl;

	std::unordered_map&lt;std::string, std::string&gt; empRecordsUnOrder;

	// insert an entry
	empRecordsUnOrder.insert({ "MAR", "Maria" });
	empRecordsUnOrder["CHR"] = "Christoph";
	empRecordsUnOrder.insert(std::make_pair("SEB", "Sebastian"));

	std::cout &lt;&lt; "Employee Records using Unordered Map\n";
	for (const auto&amp; [key, val] : empRecordsUnOrder)
		std::cout &lt;&lt; "Emp Code: " &lt;&lt; key &lt;&lt; " , Emp Name: " &lt;&lt; val &lt;&lt; std::endl;

	return 0;
}
</code></pre>

<pre><code>Output:
Employee Records using Ordered Map
Emp Code: CHR , Emp Name: Christoph
Emp Code: MAR , Emp Name: Maria
Emp Code: SEB , Emp Name: Sebastian


Employee Records using Unordered Map
Emp Code: MAR , Emp Name: Maria
Emp Code: CHR , Emp Name: Christoph
Emp Code: SEB , Emp Name: Sebastian
</code></pre>

<p>Internally, the maps are implemented using <strong><em>Self-balancing Binary Search Tree (like Red-Black Tree)</em></strong>. That is how the key order is maintained. Due to this, ordered 
maps are expensive in insertion, deletion and search operations. The complexity of all three operations is <strong><em>log(n)</em></strong>. Also the maps needs to reordered after every insert and delete operation.</p>

<p>On the other hand, unordered maps are implemented using <strong><em>Hash Table</em></strong> since they don’t require any ordering. The average time complexity is <strong><em>O(1)</em></strong> and <strong><em>O(n)</em></strong> in worst case for insert, delete and search operations.</p>

<h3 id="multimaps">Multimaps</h3>

<p>We read above about maps and that every key in a map should be unique i.e. no two values can have the same key. Multimap is different in a way that it can store two values with same key. Similar to maps, C++ STL provides ordered multimaps (std::multimap) and unordered multimaps (std::unordered_multimap). Ordered multimaps store the keys in sorted order. Unordered multimaps store the keys in random order, but the pairs with same key value are stored together. Internal implementation is similar to maps.</p>]]></content><author><name>Parika Goel</name></author><category term="Other" /><summary type="html"><![CDATA[Ordered vs Unordered Maps]]></summary></entry><entry><title type="html">C++ Sets</title><link href="https://parikagoel.github.io/2022/03/22/cpp-sets.html" rel="alternate" type="text/html" title="C++ Sets" /><published>2022-03-22T00:00:00+00:00</published><updated>2022-03-22T00:00:00+00:00</updated><id>https://parikagoel.github.io/2022/03/22/cpp-sets</id><content type="html" xml:base="https://parikagoel.github.io/2022/03/22/cpp-sets.html"><![CDATA[<h3 id="ordered-vs-unordered-sets">Ordered vs Unordered Sets</h3>

<p>Sets are different from maps in a way that map stores key-value pairs whereas set stores only keys.
C++ STL provides <strong><em>std::set</em></strong> container which stores the elements in sorted order.<br />
Another STL container <strong><em>std::unordered_set</em></strong> stores the elements in random order.
All the elements should be unique in both the containers.</p>

<p>An example usage is as below:</p>

<pre><code>#include &lt;iostream&gt;
#include &lt;set&gt;
#include &lt;unordered_set&gt;

int main()
{
	std::set&lt;std::string&gt; empNames;

	// insert an entry
	empNames.insert("Maria");
	empNames.insert("Christoph");
	empNames.insert("Sebastian");

	std::cout &lt;&lt; "Employee Names using Ordered set\n";
	for (const auto&amp; name : empNames)
		std::cout &lt;&lt; "Emp Name: " &lt;&lt; name &lt;&lt; std::endl;

	std::cout &lt;&lt; std::endl &lt;&lt; std::endl;

	std::unordered_set&lt;std::string&gt; empNamesUnOrder;

	// insert an entry
	empNamesUnOrder.insert("Maria");
	empNamesUnOrder.insert("Sebastian");
	empNamesUnOrder.insert("Christoph");

	std::cout &lt;&lt; "Employee Names using Unordered Set\n";
	for (const auto&amp; name : empNamesUnOrder)
		std::cout &lt;&lt; "Emp Name: " &lt;&lt; name &lt;&lt; std::endl;

	return 0;
}
</code></pre>

<pre><code>Output:
Employee Records using Ordered Map
Emp Code: CHR , Emp Name: Christoph
Emp Code: MAR , Emp Name: Maria
Emp Code: SEB , Emp Name: Sebastian


Employee Records using Unordered Map
Emp Code: MAR , Emp Name: Maria
Emp Code: CHR , Emp Name: Christoph
Emp Code: SEB , Emp Name: Sebastian
</code></pre>

<p>Internally, the maps and sets are implemented in the same manner. The sets are implemented using <strong><em>Self-balancing Binary Search Tree (like Red-Black Tree)</em></strong>.
The complexity of all three operations - search, insert and delete is <strong><em>log(n)</em></strong>.
Unordered sets are implemented using <strong><em>Hash Table</em></strong>. The elements of the unordered set are hashed into indices of the hash table so that 
the insertion is always randomized. The average time complexity is <strong><em>O(1)</em></strong> and <strong><em>O(n)</em></strong> in worst case for insert, delete and search operations.</p>

<h3 id="multisets">Multisets</h3>

<p>We read above about sets and that each element in the set should be unique i.e sets does not allow duplicate elements. Multisets are different from sets in a way that it allows duplicate values. Like sets, multisets are also ordered (std::multiset) and unordered (std::unordered_multiset). The internal implementation of ordered/unordered multiset is similar to ordered/unordered set in that they both use self-balancing BST/hash table, but in case of multiset, a separate count value is also associated with each element to denote the number of entries for each element.</p>]]></content><author><name>Parika Goel</name></author><category term="Other" /><summary type="html"><![CDATA[Ordered vs Unordered Sets]]></summary></entry></feed>