Better_Software_Header_MobileBetter_Software_Header_Web

Find what you need - explore our website and developer resources

C++23 Will Be Really Awesome

(a blog for April Fools Day)

void f(int x);
f(1234);  // OK, intended: called with an int
f(3.14);  // Not really intended (called with double), still legal
// C++11:
void f(int x);
template <typename T> void f(T) = delete;

f(42);   // OK
f(3.14); // ERROR
// C++11/14, SFINAE
template <typename T>
std::enable_if_t<std::is_same_v<T, int>> f(T x);

// C++20: concepts
void f(std::same_as<int> auto x);
void f(really int x);

f(42);   // OK
f(3.14); // ERROR
really int i = getInt();    // OK
really int j = getDouble(); // ERROR
class String {
    const char *data;
    int len;

public:
    void a(int) const;
    void b() const;
    void c();
};

void String::c()
{
    a(len * 42);
    a(len * 42);
    b();
}
String::c():
        push    rbp
        imul    esi, DWORD PTR [rdi+8], 42
        mov     rbp, rdi
        call    String::a(int) const
        imul    esi, DWORD PTR [rbp+8], 42
        mov     rdi, rbp
        call    String::a(int) const
        mov     rdi, rbp
        pop     rbp
        jmp     String::b() const
class String {
    const char *data;
    int len;

public:
    void a(int) really const;
    void b() const;
    void c();
};
String::c():
        push    r12
        push    rbp
        mov     rbp, rdi
        sub     rsp, 8
        imul    r12d, DWORD PTR [rdi+8], 42
        mov     esi, r12d
        call    String::a(int) const
        mov     rdi, rbp
        mov     esi, r12d
        call    String::a(int) const
        add     rsp, 8
        mov     rdi, rbp
        pop     rbp
        pop     r12
        jmp     String::b() const
enum class MyEnum {
  E1, E2, E3
};
int calculate(MyEnum e)
{
  switch (e) {
  case MyEnum::E1: return 42;
  case MyEnum::E2: return 51;
  case MyEnum::E3: return 123;
  }
}
int calculate(MyEnum e)
{
  switch (e) {
  case MyEnum::E1: return 42;
  case MyEnum::E2: return 51;
  case MyEnum::E3: return 123;
  // for the love of kittens, DO NOT add a default: !!!
  }

  assert(false);
  return -1; // impossible
}
void bad() {
  MyEnum nonsense = static_cast<MyEnum>(-1);
  int result = calculate(nonsense); // whops!
}
enum class really MyEnum {
  E1, E2, E3
};

int calculate(MyEnum e)
{
  switch (e) {
  case MyEnum::E1: return 42;
  case MyEnum::E2: return 51;
  case MyEnum::E3: return 123;
  }
  // no warning, all cases are handled
}

void bad() {
  MyEnum nonsense = static_cast<MyEnum>(-1); // UB, -1 is not an enumerator
}
void f(const std::string &s); // 1) lvalue reference
void f(std::string &&s);      // 2) rvalue reference

std::string str = "hello";
f(str);             // calls 1
f("hello"s);        // calls 2
f(std::move(str));  // calls 2
template <typename T> void f(const T &obj); // 1) lvalue reference
template <typename T> void f(T &&obj);      // 2) rvalue reference...?
std::string s = "hello";
f(s);  // call f on a lvalue
template <typename T> void f(const T &obj); // lvalue reference

template <typename T>
  std::enable_if_t<!std::is_reference_v<T>>
f(T &&obj);      // T must not be a reference => T&& is a rvalue reference
template <typename T> void f(const T really &obj);  // 1) lvalue reference
template <typename T> void f(T really &&obj);       // 2) rvalue reference! not forwarding reference
QString getString();
void print(QString);

void f() {
  auto result = QString("The result is: ") + getString();
  print(result);
}
QString a, b, c, d;
QString result = a + b + c + d;
auto result = QString("The result is: ") + getString(); // whops!
class QStringBuilder
{
  // invoked when assigning the result to `auto` variable...?
  operator auto() const { return QString(*this); }
};
class QStringBuilder
{
  // invoked when assigning the result to `auto` variable.
  really operator auto() const { return QString(*this); }
};
class C
{
   operator really int() const;
};

C c;
int    i = c;    // OK
double d = c; // ERROR

About KDAB


12 Comments

1 - Apr - 2022

RJ

1 - Apr - 2022

Bart

1 - Apr - 2022

Soroush Rabiei

1 - Apr - 2022

RJ

1 - Apr - 2022

Yacob Cohen-Arazi

2 - Apr - 2022

nyanpasu64

2 - Apr - 2022

Giuseppe D'Angelo

Each enumeration also has an underlying type. The underlying type can be explicitly specified using an enum-base. For a scoped enumeration type, the underlying type is int if it is not explicitly specified. In both of these cases, the underlying type is said to be fixed.

9 - Apr - 2022

alagner

10 - Apr - 2022

Giuseppe D'Angelo

8 - May - 2022

LorenDB

22 - Jun - 2022

Sebastian

22 - Jun - 2022

Giuseppe D'Angelo

GiuseppeD'Angelo

Giuseppe D’Angelo

Senior Software Engineer

Learn Modern C++

Learn more