C++20/23: Prefer This / Prefer That

This section gathers the modern C++ rules from the original document.

1. Special Members: = default / = delete

  • Clear intent, zero boilerplate, follows Rule of 0/5/6.

class Solver
{
public:
	Solver() = default;
	~Solver() = default;
	Solver(Solver const &) = delete;
	Solver &operator=(Solver const &) = delete;
};

2. override / final

  • Don’t repeat virtual in derived classes. Use override; consider final where relevant.

class Derived : public Base
{
public:
	void run() override;
};

3. enum class

  • Scoped and type-safe enums.

enum class Mode { A, B, C };

4. <⇒ defaulted comparisons

  • Generate comparisons with one line.

struct Point
{
	int x{}, y{};
	friend auto operator<=>(Point const &, Point const &) = default;
};

5.

  • Mark results that must not be ignored.

[[nodiscard]] double computeEnergy(Mesh const &mesh);

6. constexpr / consteval / constinit

  • constexpr: usable at compile time; consteval: must be compile-time; constinit: constant-initialized static (avoids static init order issues).

constexpr int square(int x) { return x*x; }
consteval int scaled(int x) { return x*42; }
constinit static int S_threshold = 10;

7. inline constexpr globals

  • Avoid ODR issues for constants in headers.

inline constexpr double kPi = 3.14159265358979323846;

8. string_view / span

  • Accept data without owning/copying.

void logName(std::string_view name);
void scale(std::span<double const> v, double factor);

9. ranges

  • Clear intent, fewer errors than hand-written loops.

for (int x : values | std::views::drop(1))
{
	std::println("{}", x);
}

10. concepts / requires

  • Express constraints directly; simpler than SFINAE.

template <std::integral T>
T gcd(T a, T b);

11. auto for type deduction

  • Avoid accidental conversions/copies; clarify intent.

auto s = getStringLike();

12. Formatting & Printing: std::format / std::print (or fmt)

  • std::format and std::print (C++20/23) are safer and faster than iostreams or printf.

  • Feel++ uses {fmt} where standard std::format is unavailable. Both styles are acceptable.

// Standard (C++20/23)
std::string msg = std::format("rank {} of {}", rank, size);
std::println("{}", msg);

// With {fmt} (used in Feel++)
std::string msg = fmt::format("rank {} of {}", rank, size);
fmt::println("{}", msg);