...

/

Two Wrong Approaches

Two Wrong Approaches

Get started with a short motivation for concepts.

Concepts are one of the most impactful features of C++20. Consequently, it is an ideal starting point to present the core language features of C++20.

Prior to C++20, we had two diametrically opposed ways to think about functions or classes: defining them for specific types or defining them for generic types. In the latter case, we call them function templates or class templates. Both approaches have their own set of problems. Let’s discuss them.

Too specific

It’s tedious work to overload a function or reimplement a class for each type. To avoid that burden, type conversion often comes to our rescue. What seems like a rescue is often a curse.

Press + to interact
#include <iostream>
void needInt(int i) {
std::cout << "int: " << i << '\n';
}
int main() {
std::cout << std::boolalpha << '\n';
double d{1.234};
std::cout << "double: " << d << '\n';
needInt(d);
std::cout << '\n';
bool b{true};
std::cout << "bool: " << b << '\n';
needInt(b);
std::cout << '\n';
}

In the first case (line 10), I start with a double and end with an int (line 12). In the second case, I start with a bool (line 16) and also end with an int (line 18).

The program exemplifies two implicit conversions.

Narrowing conversion

Invoking getInt(int a) with a double gives you a narrowing conversion. A narrowing conversion includes a loss in accuracy, which we should avoid.

Integral promotion

But the other way around is also not better. Invoking getInt(int a) with a bool promotes the bool to an int. Surprised? Many C++ developers don’t know which data type they get when they add two bools ...