20 C++17/20


C++ 17
Karta Features of c++17 (link)

Karta Features of c++ 20(link)

Handy C++17 Features (link)

std::optional 

std::variant

if constexpr

C++20 art LINK

C++20 Filmik cppcon2020


.......................................
When you see an article about new C++ features, most of the time you’ll see a description of major elements. Looking at C++17, there are a lot of posts (including articles from this blog) about structured bindings, filesystem, parallel algorithms, if constexpr, std::optional, std::variant… and other prominent C++17 additions.

In this article, I’ll show you 17 smaller C++17 things that will improve your code.

The Language
1. Dynamic Memory Allocation for Over-Aligned Data
2. Inline Variables
3. __has_include Preprocessor Expression
The Standard Library
4. Variable Templates for Traits
5. Logical Operation Metafunctions
6. std::void_t Transformation Trait
7. std::from_chars
8. Splicing for maps and sets
9. try_emplace() Method
10. insert_or_assign() Method
11. Return Type of Emplace Methods
12. Sampling Algorithms
13. gcd(), lcm() and clamp()
14. Shared Pointers and Arrays
15. std::scoped_lock
Removed Elements
16. Removing auto_ptr
17. Removing Old functional Stuff
.........................................



std::optional 

Std::optional dodaje nam możliwość zwrócenia stanu "pusty" - nullopt przy różnych typach.
Stan "pusty" - nullopt, może być sprawdzany warunkiem IF jak w przykładzie:

Przykład działania optional


#include <iostream>
#include <vector>
#include <optional>

void Process(int) { };

int main()
{
    std::vector<int> vec { 1, 2, 3, 4, 5, 6, 7, 101, 8, 9 };
    std::optional<int> largerThan100;
    
    for (auto& elem : vec)
    {
        Process(elem);
        
        if (elem > 100 && !largerThan100)
            largerThan100 = elem;
    }
    
    // later on selected elements...
    if (largerThan100)
        std::cout << *largerThan100;
}



Można również zwrócić taki stan za pomocą return std::nullopt  jak w poniższym przykładzie:
Drugi przykład działania option

#include <iostream>
#include <vector>
#include <optional>

template <typename TContainer>
std::optional<typename TContainer::value_type> FindVal(const TContainer& container, const typename TContainer::value_type& key)
{
 auto it = std::find(std::begin(container), std::end(container), key);
 if (it != std::end(container))
  return *it;

 return std::nullopt; // or std::nullopt
}

int main()
{
 std::vector<int> v{ 1, 2, 3, 4, 5, 6, 7 };
 auto i = FindVal(v, 1);
 if (i)
  std::cout << *i;
}




std::variant

Std::variant może przyjmować dowolne, wcześniej określone typy, slbo stan pusty (tu realizowany za pomocą std::monostate )

#include <iostream>
#include <vector>
#include <optional>
#include <variant>
#include <cmath>

// aX^2 + bX + c
using TRoots = std::variant<std::monostate, double, std::pair<double, double>>;

TRoots FindRoots(double a, double b, double c)
{
    const auto delta = b*b-4*a*c;

    if (delta > 0.0)
    {
        auto p = sqrt(delta);
        double x1 = (-b + p)/(2*a);
        double x2 = (-b - p)/(2*a);
        return std::pair(x1, x2);
    }
    else if (delta == 0.0)
    {
        return -b/(2*a);
    }
    
    return std::monostate();
}

void ShowRoots(const TRoots& roots)
{
    switch (roots.index())
    {
        case 0: std::cout << "no roots!\n"; break;
        case 1: std::cout << std::get<1>(roots) << '\n'; break;
        case 2: std::cout << std::get<2>(roots).first << ", " << std::get<2>(roots).second << '\n'; break;
    }
}

int main()
{
    ShowRoots(FindRoots(1, -3, 4));
    ShowRoots(FindRoots(-4, 12, -9));
    ShowRoots(FindRoots(2, -11, 5));
}

Patrz na przykład zastosowania std::variant jako nowoczesnej maszyny stanów.
LINK





if constexpr

Pozwala wybierać gałęzie na poziomie kompilowania  na podstawie warunków constexpr (wyrażenie stałe).



template <typename T>
auto get_value(T t) {
  if constexpr (std::is_pointer_v<T>)
    return *t;
  else
    return t;
}

Uproszcza kod Templatów, szczególnie jeśli używane SFINAE
 (Niepowodzenie podstawienia nie jest błędem (SFINAE) odnosi się do sytuacji w C ++, w której nieprawidłowe zastąpienie parametrów szablonu samo w sobie nie jest błędem)


wiecej 303 i 58 (książka Filipek)