TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.35K subscribers
Post #212 3.05K
​static_assert и if constexpr

Вернемся к прошлому примеру с функцией to\_str, но сделаем ее немножко безопасней.

template <typename T>
std::string to_str(T t) {
if constexpr (std::is_constructible_v<std::string, T>)
return t;
else if constexpr (std::is_arithmetic_v<T>)
return std::to_string(t);
else
static_assert(false, "cannot convert type to std::string");
}


Все просто. Функция std::to_string имеет перегрузки только для тривиальных арифметических типов, поэтому чтобы ее использовать и получить ошибку, нужно провести проверку на эту арифметичность. Если переданный в функцию to\_str тип не конструируется в строку или не является арифметическим типом, то не совсем понятно, как такой тип переводить в строку. Точнее так: в каждом конкретном случае мы можем сказать как, но общего поведения нет. Поэтому, чтобы детектировать такие нештатные ситуации, я поставлю ассерт времени компиляции.

И вроде всё хорошо, но да не всё...

Дело в том, что при попытке скомпилировать этот пример, процесс прервется на этом ассерте даже в том случае, когда мы попадем в первые две ветки.

Тут в чем прикол. Согласно стандарту, если хотя бы в одной из веток if constexpr не может быть сгенерировано ни одной валидной специализации, то программа - ill-formed и это ошибка. И вправду, false всегда будет false, как бы мы там не тужились родить что-то валидное.

Но даже сам cppreference предлагает нам способ обойти эту неприятную бяку. Мы можем подставить вместо false шаблонное constexpr типазависимое выражение, которое будет возвращать false. И тогда все магическим образом заработает.

template<typename>
inline constexpr bool dependent_false_v = false;

template <typename T>
std::string to_str(T t) {
if constexpr (std::is_constructible_v<std::string, T>)
return t;
else if constexpr (std::is_arithmetic_v<T>)
return std::to_string(t);
else
static_assert(dependent_false_v<T>, "cannot convert type to std::string");
}


Видимо из-за того, что шаблон можно вручную специализировать, то теоритически возможна специализация, которая будет возвращать true. И даже если она еще не инстанцирована, то возможность-то остается. Поэтому компилятор пропускает такую конструкцию.

Однако ситуация изменилась с приходом С++23, но об этом мы поговорим завтра.

Find loopholes in the system. Stay cool.

#cpp17 #template
  • 🔥 15
  • 👍 8
  • ❤ 3
  • 😁 1
More from @grokaemcpp
  1. Oct 14, 2026​​Что внутри std::condition_variable? #опытным Более менее все знакомы с примитивом синхро…
  2. Oct 12, 2026​​WAT #новичкам Как вы думаете, результат выражения: bool math = -1 < 1U; будет правдой ил…
  3. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  4. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  5. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
  6. Oct 1, 2026​​Stacktrace. Tips #опытным Чтобы полноценно работать со стандартными трейсами, нужно знат…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →