Fold Expressions (c++17)

Fold Expressions can be used to make code that uses variadic templates more compact and easier to read by allowing you to use operators on argument packs. This works as followed:

template<typename... T>
float sum(T... t) {
	return(t + ...);
}

If you would want do write the same code without expression folding it would look something like this:

template<typename... T>
float sum(T... t) {
	typename std::common_type<T...>::type_result{};
	(void) std::initializer_list<float>{ (rval += t, 0)... };
	return rval;
}

sizeof…

During my researh for fold expressions I found out sizeof... exists. It returns the number of elements in the parameter pack.

Aggregate Initializations And Uniform Initializations (c++11,17)

A uniform initialization is basically a easy way to intialize structs without creating a constructor. So instead of writing:

struct S {
	S(x, y) : x(x), y(y) {}
	int x;
	int y;
}

S s(1, 1);

You can now write:

struct S {
	int x;
	int y;
}

S s{1, 1}

But when you have a class hierchy this won’t work in c++11/14. But since c++17 it is possible to use a bracket initialization in a bracket initialization. It works like this:


struct A {
	int x;
}

struct B : A {
	int y;
}

B b{{1}, 1}

If you leave the aggregate initialization empty it will default the variables from the parent to 0 or nullptr.

__has_include (c++17)

has_include can be used to make system and compiler specific includes way easier to write since you can test if the system has a include.

For example:

#if __has_include(<unistd.h>)
#include <unistd.h>
#endif

This is much more easier to write compared to:

#if defined(__linux__) || defined (__unix__) || defined (__APPLE__)
#include <unistd.h>
#endif

C++17’s new attribute’s

[[falltrough]]

suppressed switch statement case falltrough warnings.

switch(int x) {
	case 1:
		something();
		[[falltrough]]
	case 2:
		something();
}

[[maybe_unused]]

suppresses unused parameter warnings. I am hower not sure when you would ever want this instead of just typing for example:

int main(int arc, [[maybe_+unused]] const char* argv[])

is longer then

int main(int arc, const char* /*argv[]*/)

Fortunatly you can also use it for return values.

[[maybe_unused]] bool create_sprite() { return true; } 

This leads into the [[nodiscard]] attribute.

[[nodiscard]]

[[nodiscard]] is the oposite of maybe_unused. It tells the compiler to warn the user if a return value is discarded.

[[nodiscard]] bool something() { return false; }

// Throws warning.
something();

This works very nicely when returning classes or structs.

[[nodiscard]] struct S {
	int x;
}

S something() { return {}; }

// Throws warning.
something();