Daily bit(e) C++. Условный оператор
Daily bit(e) C++ #3, Условный (он же тернарный) оператор.
Условный оператор, также известный как тернарный оператор, по сути, является инструкцией if
в виде выражения.
Этот оператор последовательный. Сначала вычисляется левая часть со всеми ее побочными эффектами, а затем один из правых операндов (в зависимости от логического значения первого операнда).
Если типы двух правых аргументов различаются, можно применить преобразования для получения совместимого общего типа, результирующего типа выражения.
До того, как C++17 представил if constexpr
, тернарный оператор также был основным способом внедрения логики в выражение constexpr
.
#include <string>
#include <memory>
#include <stdexcept>
#include <array>
#include <iostream>
struct A {};
struct B : A {};
struct MustBeInit
{
MustBeInit(int v) : v(v) {}
int v;
};
int main()
{
// простая арифметическая логика:
int x = 1;
int y = 2;
int abs_diff = x < y ? y - x : x - y;
// Полезно для инициализации переменных,
// которые не поддерживают инициализацию по умолчанию:
MustBeInit m = true ? 1 : 2;
// До C++17 условный оператор был основным
// способом внедрения логики в код constexpr.
constexpr bool has_many = true;
std::array<int, has_many ? 1024 : 8> arr;
// При смешивании типов разрешены стандартные
// преобразования, например:
static_assert(std::is_same_v< // int->double
decltype(true ? 2.0 : 1), double
>);
static_assert(std::is_same_v< // производный класс в базовый
decltype(true ? A() : B()), A
>);
// Выражения throw разрешены, так как они прерывают поток:
auto ptr = std::make_unique<std::string>("abc");
size_t len = ptr ? ptr->length() :
throw std::runtime_error("Null pointer dereference.");
// Если обе стороны являются выражениями throw,
// результат будет void.
static_assert(std::is_same_v<
decltype(true ? throw 1 : throw 2), void
>);
// При смешивании cv-квалификаторов (const/volatile)
// аргументы должны перекрываться, но в результате
// получается наиболее квалифицированный тип.
int a = 1;
const int& b = 2;
int& c = a;
static_assert(std::is_same_v<
decltype(true ? b : c), const int&
>);
}
Открыть пример на Compiler Explorer.