templates with strings and auto in c++17 - tum
TRANSCRIPT
Technical University of Munich
Faculty of Informatics
Chair for Computer Aided Medical Procedures
Tobias Jülg
Garching, 05. June 2018
Templates with Strings and auto in C++17
Trend:
Shifting calculations towards compile time
• Limited execution time
• constexpr simplified metaprogramming a lot → interesting use cases
• E. g. regex libraries that analyse strings at compile time
→Simplifying syntax for strings and pushing modern concepts like auto to template development
2Tobias Jülg (TUM)
• Motivation
• Short Reminder of Templates
• New C++17 features
− Strings as non-type Template Parameters
− Placeholder Types as Template Parameters
▪ Using auto
▪ Applications
• References
• Exercises
3Tobias Jülg (TUM)
Agenda
• Motivation
• Short Reminder of Templates
• New C++17 features
− Strings as non-type Template Parameters
− Placeholder Types as Template Parameters
▪ Using auto
▪ Applications
• References
• Exercises
4Tobias Jülg (TUM)
Agenda
• Type Templates
→ Compiler generates code with the replaced types
template <typename T> // T as typevariable
void Print(T p) {
std::cout << p << std::endl;
}
Print(0.5f); // T is deduced to float
• Non-Type Templates
→ Compiler generates code with the replaced values instead of types
→ Example: std::array
template<typename T, std::size_t N>
class Array {
T m_Array[N];
};
Array<int, 10> a;
5Tobias Jülg (TUM)
Short Reminder of Templates
• Values must be constant expressions
• Allowed types:
− const integral values, also enums
− pointers to objects/functions/members
− lvalue references to objects, functions or std::nullptr_t
• Implicit value deduction:
template<std::size_t N>
std::size_t GetSize(const int(&arr)[N]) {
return N;
}
int arr[10];
std::size_t n = GetSize(arr); //n will be 10
6Tobias Jülg (TUM)
Non-Type Templates
→ Advantages compared to passing• Values are known at compile time
• Compile time analysis, faster
• Motivation
• Short Reminder of Templates
• New C++17 features
− Strings as non-type Template Parameters
− Placeholder Types as Template Parameters
▪ Using auto
▪ Applications
• References
• Exercises
7Tobias Jülg (TUM)
Agenda
• Properties of Variables
− Linkage: internal, external or non at all
− Scope: global or local scope (heap or stack)
− Duration: static or temporary duration
• When using strings as arguments− Linkage is always required
− You can’t pass string literals directly, instead const char*
− Rules for relaxed over time
• Situation before C++17− C++98 pointer parameters work only with external linkage
− C++11 internal linkage possible but only global scope
8Tobias Jülg (TUM)
Strings as Non-Type Template Parameters
In C++17
→Using pointers, defined in the current scope possible when declared static
→Still two lines of code but doesn’t pollute the global namespace
→Easier to use C-Strings
→Upcoming use cases: Compile-time JSON and regular expression parsing
template<const char *str>
class regex_parser { };
extern const char hello[] = "[a-zA-Z]*"; //external linkage
const char hello11[] = "C++11 [a-zA-Z]*"; //internal linkage
void foo() {
regex_parser<hello> msg; //okay for all C++ versions
regex_parser<hello11> msg11; //okay since C++11
static const char hello17[] = "C++17 [a-zA-Z]*"; //static declaration
regex_parser<hello17> msg17; //okay since C++17
}
9Tobias Jülg (TUM)
Strings as Non-Type Template Parameters
Before C++17
• You could pass a normal pointer to a
class template
• Compile-time functions returning the
address weren’t possible
• Except functions returning a nullptr
• Implementation only to evaluate the
return type
→ In C++17 by allowing static pointers this
inconsistency was fixed
10Tobias Jülg (TUM)
Pointers returned by Functions
template<int *p> struct A {};int n;A<&n> a; // OK
constexpr int *q() { return nullptr; }A<q()> c; // OK before C++17 because it
// returns a nullptr
constexpr int *p() { return &n; }A<p()> b; // error before C++17, now OK
• Motivation
• Short Reminder of Templates
• New C++17 features
− Strings as non-type Template Parameters
− Placeholder Types as Template Parameters
▪ Using auto
▪ Applications
• References
• Exercises
11Tobias Jülg (TUM)
Agenda
Before C++17, when you didn't want to write a explicit type for a non-type template
// I don't want to be specified on int here
template<int N> struct S { };
the following workaround was possible. Be x of any type:
template <typename T, T N> struct S { }; // definition
template<typename T> void foo(T x) {
S<decltype(x), x> s; // instantiation, x is of any type
}
• Type of x isn’t needed but has to be passed
→ redundancy
• Can get more complicated when passing function without fixed type
→ variadic functions
12Tobias Jülg (TUM)
Placeholder Types as Template Parameters
• Motivation
• Short Reminder of Templates
• New C++17 features
− Strings as non-type Template Parameters
− Placeholder Types as Template Parameters
▪ Using of auto
▪ Applications
• References
• Exercises
13Tobias Jülg (TUM)
Agenda
• Like you use it in lambdas you can also use it with templates now
• In C++ 17 the auto keyword was introduced for non-typed templates
• → known as template <auto>
• → You don’t have to mind the types and let the compiler deduce it
• → Extremely useful for passing a function pointer with non-fixed types
Way to do the previous example in C++17:
template<auto N> struct S { };
S<42> s1; // OK type N is int
S<'a'> s2; // OK type N is char
S<2.5> s3; // Error
→ Can only deduce allowed types for templates
14Tobias Jülg (TUM)
Using auto as Template Parameter
• You can also qualify auto like you do when using it with normal variables, for example to
require a pointer:
template<const auto* p>struct S { };
• Partial specialization
template<int M, int E> struct S { /*do some recursion*/ };
template<int M> struct S<M, 0> {
// end recursion when E is 0 --> different implementation
};
→ Also works for the auto types, for example for int
template<auto N> struct S { };
template<int N> struct S<N> {
// specialized implementation when N is of type int
};
15Tobias Jülg (TUM)
Further features
• Even class template argument deduction is supported
template<typename T, auto N> struct A {
A(const std::array<T, N>&) { }
};
std::array<double, 10> sa1;
A a1{sa1}; // OK
→ Compiler deduces the types T being double and N being std::size_t without specifying it
16Tobias Jülg (TUM)
Further features
• Motivation
• Short Reminder of Templates
• New C++17 features
− Strings as non-type Template Parameters
− Placeholder Types as Template Parameters
▪ Using of auto
▪ Applications
• References
• Exercises
17Tobias Jülg (TUM)
Agenda
auto allows to pass both a character or a c-string as template parameter
→ create a print function that accepts any number of parameters and make the separator
type independent:
template<auto Sep = ' ', typename First, typename... Args>
void print(const First& first, const Args&... args) {
std::cout << first;
auto outWithSpace = [](const auto& arg) {
std::cout << Sep << arg;
};
(..., outWithSpace(args));
std::cout << '\n’;
}
18Tobias Jülg (TUM)
Application: Parameterizing Templates
auto allows to pass both a character or a c-string as template parameter
→ create a print function that accepts any number of parameters and make the separator
type independent:template<auto Sep = ' ', typename First, typename... Args>
void print(const First& first, const Args&... args) {
std::cout << first;
auto outWithSpace = [](const auto& arg) {
std::cout << Sep << arg;
};
(..., outWithSpace(args));
std::cout << '\n’;
}
Pass the default Argument for the first template:std::string s{ "world" };
print(7.5, "hello", s); // prints: 7.5 hello world
Pass a string literal as separator:static const char sep[] = ", ";
print<sep>(7.5, "hello", s); // prints: 7.5, hello, world
19Tobias Jülg (TUM)
Application: Parameterizing Templates
→ Basically any type that can
be used as template
parameter
→ Runtime improvement for
logger functions
• Metaprogramming constants also needed to pass the type
• auto improves the instantiation process of these constants:
→ Like auto with normal variables you don’t need to pass the type
20Tobias Jülg (TUM)
Application: Defining Metaprogramming Constants
template<auto v>struct constant{
static constexpr auto value = v;};using i = constant<42>;
template<typename T, T v>struct constant{
static constexpr T value = v;};using i = constant<int, 42>;
And when using a sequence with variadic template syntax instead of
template<typename T, T... Elements>
struct sequence {};
using indexes = sequence<int, 0, 3, 4>;
There are new possibilities to parameterize a list of constant template arguments:
• At least one argument and all having the same type:
template<auto V1, decltype(V1)... VS> struct HomoValueSequence {};
• Even compile-time objects representing a heterogeneous list of values like a tuple:
template<auto... VS> struct HeteroValueSequence {};
using tuple = HeteroValueSequence<0, 'h', true>;
21Tobias Jülg (TUM)
Application: Defining Metaprogramming Constants
template<typename T, T... Elements> class Foo0 {};
template<auto... VS> class Foo1 { };
template<auto V1, decltype(V1)... VS> class Foo2 { };
Foo0<1, 'a', true> vals1;
Foo0<int, 1, 2, 3> vals2;
Foo0<> vals3;
Foo1<1, 2, 3> vals4;
Foo1<1, 'a', true> vals5;
Foo1<> vals6;
Foo2<> vals7;
Foo2<1, 'a', true> vals8;
Foo2<1, 2, 3> vals9;
22Tobias Jülg (TUM)
Which lines won’t compile?
• Nicolai Josuttis, C++17 - The Complete Guide, ch. 12, 13, leanpub, 02.2017
• Louis Dionne, http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0424r2.pdf,
visited May 2018
• Louis Dionne, https://ldionne.com/2015/11/29/efficient-parameter-pack-indexing/ visited
May 2018
• Richard Smith, http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4268.html
visited May 2018
• James Touton, http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0127r1.html
visited May 2018
23Tobias Jülg (TUM)
References