Open In App

Features of C++ 20

C++ has a tradition of introducing new improvements and features in every 3 years in the form of a standard. With the last standard having released in 2017 as C++ 17, C++20 is going to be the latest standard. Below here are some major features in C++ 20:

C++ Concepts library:

The concepts library provides definitions of fundamental library concepts that can be used to perform compile-time validation of template arguments and perform function dispatch based on properties of types. These concepts provide a base for educational reasoning in programs.



This section has around 15 concepts that should be self-explanatory. These concepts express relationships between types, type classifications, and fundamental type properties.

Defined in header <concepts>
Defined in namespace std

Syntax:



template<class T>
concept integral = is_integral_v<T>;
template<class T>
concept signed_integral = integral<T> && is_signed_v<T>;

template<class T>
concept unsigned_integral = integral<T> && !signed_integral<T>;

template<class T>
concept floating_point = is_floating_point_v<T>;
 

3-way comparisons:

The three-way comparison operator expressions is of the form:

lhs <=> rhs 

The spaceship operator looks like <=> and its official C++ name is the 3-way comparison operator. It is called so because it is used by comparing two objects, then comparing that result with 0:

(x <=> y) < 0 is true if x < y
(x <=> y) > 0 is true if x > y
(x <=> y) == 0 is true if x and y are equal/equivalent.

The 3-way comparison operator not only let express orderings and equality between objects but also the characteristics of the relations. The spaceship operator is a very welcome addition to C++. It gives us more expressiveness in how to define our relations, allows us to write less code to define them, and avoids some performance pitfalls of manually implementing some comparison operators in terms of others.

Program 1:




// C++ program to illustrate the
// above concepts
#include <bits/stdc++.h>
#include <compare>
using namespace std;
 
// Driver Code
int main()
{
    int a = 91, b = 110;
    auto ans1 = a <=> b;
 
    if (ans1 < 0) {
        cout << "a < b\n";
    }
    else if (ans1 == 0) {
        cout << "a == b\n";
    }
    else if (ans1 > 0) {
        cout << "a > b\n";
    }
 
    vector<int> v1{ 3, 6, 9 };
    vector<int> v2{ 3, 6, 9 };
    auto ans2 = v1 <=> v2;
 
    if (ans2 < 0) {
        cout << "v1 < v2\n";
    }
    else if (ans2 == 0) {
 
        cout << "v1 == v2\n";
    }
    else if (ans2 > 0) {
 
        cout << "v1 > v2\n";
    }
 
    cout << endl;
}

Output:

Map/Set contains:

Syntax:

std::map<Key, T, Compare, Allocator>::contains

std::set<T>::contains

It gives a much easier way to check if a key is present in the associative container(set or map) in C++20. It replaces the find built-in function.

Program 2:




// C++ program to illustrate the
// above concepts
#include <iostream>
#include <map>
 
// Driver Code
int main()
{
    // Map
    std::map<int, char> M = { { 1, 'a' },
                              { 2, 'b' } };
 
    // Check if M has key 2
    if (M.contains(2)) {
        std::cout << "Found\n";
    }
    else {
        std::cout << "Not found\n";
    }
    return 0;
}

Output:

Range-based for loop with Initialization:

The range-based for loop changed in C++17 to allow the begin() and end() expressions to be of different types and in C++20, an init-statement is introduced for initializing the variables in the loop-scope. It allows us to initialize the container we wish to loop through in the range-declaration itself.

Syntax:

for (init-statement(optional) range_declaration : range_expression)  
{  
         /* loop body */ 
}

Program 3:




// C++ program to illustrate the
// above concepts
#include <iostream>
using namespace std;
 
// Driver Code
int main()
{
 
    for (std::vector v{ 1, 2, 3 }; auto& e : v) {
        std::cout << e;
    }
}

Output:

New identifiers(import, module):

Program 4:




// C++ program to illustrate the
// above concepts
// helloworld.cpp module declaration
export module helloworld;
 
// Import declaration
import<iostream>;
 
// Export declaration
export void hello()
{
    std::cout << "Hello world!\n";
}




// main.cpp import declaration
import helloworld;
 
// Driver Code
int main()
{
    hello();
}

Output:

Calendar and time zone library:

The chrono library of C++ 11/14 was extended with a calendar and time-zone feature. The calendar consists of types, which represent a year, a month, a day of a weekday, or n-th weekday of a month. These elementary types can be combined with complex types such for example year_month, year_month_day, year_month_day_last, years_month_weekday, and year_month_weekday_last. The operator “/” is overloaded for the convenient specification of time points. Additionally, we will get with C++20 new literals: d for a day and y for a year.

Due to the extended chrono library, the following functions are easy to implement:

Syntax:

Defined in header <chrono>
Defined in namespace std::chrono

Example:

auto date1 = 2020y/sep/8;
auto date2 = 21d/oct/2018;
auto date3 = jan/27/2019;

std::string functions:

ends_with(“suffix”): Checks if the string ends with the given suffix.
starts_with(“prefix”) :Checks if the string view starts with the given prefix.

Program 5:




// C++ program to illustrate the
// above concepts
#include <iostream>
using namespace std;
 
// Driver Code
int main()
{
    std::string str = "GeeksforGeeks";
 
    // Check string str starts_with Geeks
    if (str.starts_with("Geeks")) {
        std::cout << "true" << endl;
    }
    else {
        std::cout << "false" << endl;
    }
 
    // Check string str ends_with Geeks
    if (str.ends_with("for")) {
 
        std::cout << "true" << endl;
    }
    else {
 
        std::cout << "false" << endl;
    }
}

Output:

Array bounded/unbounded:

Program 6:




// C++ program to illustrate the
// above concepts
#include <iostream>
#include <type_traits>
 
// Class A
class A {
};
 
// Driver Code
int main()
{
 
    std::cout << std::is_unbounded_array_v<A> << '\n';
    std::cout << std::is_unbounded_array_v<A[3]> << '\n';
    std::cout << std::is_unbounded_array_v<int[]> << '\n';
    std::cout << std::is_unbounded_array_v<int> << '\n';
    std::cout << std::is_bounded_array_v<A> << '\n';
    std::cout << std::is_bounded_array_v<A[3]> << '\n';
    std::cout << std::is_bounded_array_v<float> << '\n';
    std::cout << std::is_bounded_array_v<int> << '\n';
}

Output:

std::to_array:

It converts the given array/”array-like” object to an std::array. It creates an std::array from the one-dimensional built-in array a. The elements of the std::array is copy-initialized from the corresponding element of a. Copying or moving a multidimensional built-in array is not supported.

Program 7:




// C++ program to illustrate the
// above concepts
#include <iostream>
using namespace std;
 
// Driver Code
int main()
{
    // Returns std::array<char, 5>
    std::to_array("Geeks");
 
    std::to_array<int>(
        { 1, 2, 3 });
 
    int a[] = { 1, 2, 3 };
 
    // Returns std::array<int, 3>`
    std::to_array(a);
}

likely and unlikely attributes:

It provides a hint to the Optimizer that the labeled statement is likely/unlikely to have its body executed. Both attributes allow giving the Optimizer a hint, whether the path of execution is more or less likely.

Program 8:




// C++ program to illustrate the
// above concepts
#include <iostream>
using namespace std;
 
// Driver Code
int main()
{
    int n = 40;
    [[likely]] if (n < 100) { cout << n * 2; }
 
    [[unlikely]] while (n > 100)
    {
        n = n / 2;
        cout << n << endl;
    }
 
    n = 500;
    [[likely]] if (n < 100) { cout << n * 2; }
 
    [[unlikely]] while (n > 100)
    {
        n = n / 2;
        cout << n << endl;
    }
    return 0;
}

Output: 

References: C++ 20, CPP Reference.


Article Tags :