C++17: Not Your Father’s C++
Pat Viafore
@PatViaforever
DevSpace 2017
CSE 2050 : Programming in a Second Language
hello.c
// my first c program
#include <stdio.h>
int main()
{
printf("Hello, %sn", "World!");
return 0;
}
hello.cpp
// my first c++ program
#include <stdio.h>
int main()
{
printf("Hello, %sn", "World!");
return 0;
}
Is this all C++ is?
● std::cout?
● std::vector?
● std::map?
● std::string?
● classes w/ inheritance?
4 subsets of C++
1. The C programming language
2. Object-Oriented
3. STL library
4. Template Metaprogramming
C++ is not the language I thought it was
We’re going to look at
modern C++ and see how
it has transformed from
“C With Classes”
C++ 11
C++ 17
C++ 14
Expressiveness
Code what you mean,
mean what you code
#include <algorithm>
find_if(v.begin(), v.end(), isSpecial);
count_if(v.begin(), v.end(), isNull);
#include <algorithm>
unique_copy(v.begin(), v.end(), v2.begin());
partition(v.begin(), v.end(), isAnAdult);
#include <algorithm>
nth_element(v.begin(), v.begin()+7, v.end());
transform(v.begin(), v.end(), v.begin(),
std::bind2nd(std::plus<int>(), 5);
Lambda Expressions
[capture-group](parameters)
{
function-body
};
C++ 11
Lambda Expressions
auto isSpecial =
[](int x) { return x == 5 || x >= 13;};
std::count_if(v.begin(), v.end(), isSpecial);
C++ 11
(Smart?)
Pointers
Smart Pointers
std::unique_ptr<Widget> makeWidget() {
return make_unique<Widget>(5,12,”param”);
}
//unique pointers have single ownership
std::unique_ptr<Widget> w = makeWidget();
C++ 11/14
Smart Pointers
std::shared_ptr<Widget> makeWidget() {
return make_shared<Widget>(5,12,”param”);
}
//unique pointers have multiple ownership
std::shared_ptr<Widget> w = makeWidget();
C++ 11/14
Quality Of
Life
C++17 Destructuring C++ 17
//c++11
int i;
float f;
std::string s;
std::tie(i,f,s) = make_tuple(5, 3.4, “c++11”);
C++17 Destructuring C++ 17
//c++17
auto [i2,f2,s2] = make_tuple(5, 3.4, “C++17”);
C++17 Attributes C++ 17
switch(condition) {
case 1:
std::cout <<”Option 1n”;
break;
case 3:
std::cout <<”Exceptional Valuen”;
[[fallthrough]];
default:
break;
}
C++17 Attributes C++ 17
[[maybe_unused]] static void log() {}
#if LOGGING_ENABLED
log();
#endif
C++17 Attributes C++ 17
[[nodiscard]] int importantFunction();
[[nodiscard]] struct lockGuard {};
importantFunction(); //warning
lockGuard f();
f(); //warning
std::filesystem
Path handling
Directory handling
File/Directory Options
Symlinking
And so much more...
C++ 17
C++17 Miscellany C++ 17
namespace x::y::z {
void print() {
std::byte b = std::byte(0b1001);
b = clamp(b, std::byte(5), std::byte(8));
if(auto opt = getOpts(); opt.isConsole) {
int i = std::to_integer<int>(b);
std::cout << i << "n";
}
}
}
Concurrent and Parallel
Operations
Concurrency
std::mutex
std::thread
std::future
std::atomic
C++ 11
Reproduction of Joe Armstrong’s
picture by Yossi Kreinin
http://yosefk.com/blog/parallelism-and-concurrency-nee
d-different-tools.html
Parallelism
std::vector<int> v = {1,2,3,4,5};
auto times3 = [](int i) { return i * 3;};
std::transform(std::par, v.begin(), v.end(),
v.begin(), times3);
C++ 17
Parallelism
std::transform(std::par_vec, v.begin(),
v.end(), v.begin(), addOne);
C++ 17
Type System
Wooo!
Type Inference
auto i = 5;
auto f = 3.4
auto v = getVector();
C++ 11
Type Inference
//c++03
for(std::vector<int>::iterator i= v.begin();
i !=v.end(); ++i)
C++ 11
Type Inference
//c++11
for(auto i = v.begin(); i != v.end(); ++i);
C++ 11
Type Inference
//alternatively (also in c++11)
for(auto &i: v)
C++ 11
Type Inference (continued)
auto isSpecial = [](int x) { return x == 5; };
auto a = [](auto x, auto y) { return x + y; };
auto get_second(auto &container) {
return container.begin() + 1;
}
C++ 11/14
std::string_view
auto getNumUpperCase(std::string_view s){
return count_if(s.begin(), s.end(), isupper);
}
getNumUpperCase("One”)
getNumUpperCase("TWo"s)
getNumUpperCase(MyStr{"THR"})
C++17
std::variant
std::variant<int, float, std::string> v;
v = 5;
std::cout << std::get<int>(v) << "n";
v = "Now I'm a String!"s;
std::cout << std::get<std::string>(v) << "n";
C++17
std::variant
std::variant<int, float, std::string> v;
v = 5;
std::cout << std::get<string>(v) << "n";
// the above throws
// a bad_variant_access exception
C++17
A Quick Look at Haskell
data Custom = Option1 | Option2 Int
doSomething :: Custom -> Int
doSomething Option1 = 0
doSomething (Option2 x) = x
std::visit
template<class... Ts> struct make_visitor : Ts...
{ using Ts::operator()...; };
template<class... Ts> make_visitor(Ts...) ->
make_visitor<Ts...>;
std::variant<int, float, std::string> v;
C++17
std::visit
std::visit( make_visitor {
[](int a) { std::cout << a << " int n"; }
[](float a) { std::cout << a << " float n"; }
[](std::string a) { std::cout << a << "n"; }
}, v);
C++17
std::optional
std::optional<std::string> opt;
std::cout << opt.value_or("Missing") << "n";
opt = "Filled in value";
std::cout << opt.value_or("Missing") << "n";
C++17
std::any
auto a = std::any(12);
std::cout << std::any_cast<int>(a) << “n”;
//throws bad_any_cast exception
std::any_cast<std::string>(a)
C++17
Templates
I’ve never metaprogram I
didn’t like
Templates
std::vector<int> v;
std::vector<double> v2;
template <typename T>
class DuplicateType {
T val1;
T val2;
};
Compile-time
vs.
Runtime
Template Metaprogramming
template<int T>
int factorial() {
return factorial<T-1>() * T;
}
template <>
int factorial<0>() { return 1; }
std::cout << factorial<7>;
Variadic Templates
template <typename… Values> class Variadic{
…
}
std::tuple<int, double, std::string, float> t;
C++ 11
Fold Expressions
template <typename… Values>
auto sum(Values… values) {
return ( … + values);
}
C++ 17
constexpr
template<int32_t T>
unsigned int getBits() {
unsigned int counter = 0;
for (unsigned int i = 0; i < 32; ++i) {
if(T & (0x1 << i)) counter++;
}
return counter;
}
C++ 11
constexpr
constexpr unsigned int factorial(int n) {
return n <= 0 ? 1 : (n * factorial(n - 1));
}
int main() {
std::cout << getBits<factorial(5)>();
std::cout << factorial(5);
return 0;
}
C++ 11
If constexpr
template <typename T>
void printSpecialized(T t){
if constexpr (is_integral<T>())
std::cout << "Integral " << t << "n";
else if constexpr(is_floating_point<T>())
std::cout << "Float " << t << "n";
}
C++ 17
What’s next?
Yarr, there be
uncharted lands
ahead!
Concepts
template concept bool Fractional<T> =
Floating<T> || QuotiendField<T>;
C++ ?
Ranges
std::vector numbers = { 1, 2, 3, 4, 5 };
ranges::accumulate(numbers |
view::transform(addOne) |
view::filter(isEven) |
view::transform(invert)
, 0);
C++ ?
Reflection
template<typename T> print(T a, T b) {
std::cout
<< $T.qualified_name() << ">("
<< $a.name()<<'':<< $a.type().name()
<< ',' << $b.name()<<':'<<$b.type().name()
<< ") = ";
}
C++ ?
And many more?
tasks?
std::network IO?
coroutines?
modules?
C++ ?
Is it a bust?
Here’s my personal litmus test for whether
we’ve changed the way people program: Just
as you can take a look at a screenful of code
and tell that it’s C++11 (not C++98), if you
can look at a screenful of code and tell that
it’s C++17, then we’ve changed the way we
program C++. I think C++17 will meet that
bar.
--Herb Sutter
There are only two kinds of languages: the
ones people complain about and the ones
nobody uses.
--Bjarne Stroustrup

C++17 not your father’s c++