Однако я ожидал, что if (), который имеет false, просто не будет скомпилирован, поэтому не будет ошибок, так как это происходит во время компиляции (то есть компилятор знает, будет ли выполнен блок if () или не во время компиляции.)
Вы описываете поведение if constexpr
, которое, к сожалению, доступно только начиная с C ++ 17
Когда вы пишете
if constexpr ( some_compile_time_test )
some_code_1;
else
some_code_2;
где some_compile_time_test
- это тест, который может быть определен во время компиляции (как sizeof(S) < sizeof(D)
), компилятор компилирует some_code_1
- и полностью игнорирует some_code_2
- когда тест равен true
и наоборот в противном случае
Если вы только напишите
if ( some_test )
some_code_1;
else
some_code_2;
не важно, если тест some_test
является выводимым во время компиляции или нет: компилятор может оптимизировать код, игнорируя неиспользуемую часть, но эта часть должна быть компилируемой.
До C ++ 17 (в основном, но не только, C ++ 11 и C ++ 14) вам необходимо разработать две (или более) различных функций / методов.
Найдите «SFINAE» и «Диспетчеризация тегов», чтобы увидеть пару полезных методов.
Пример СФИНАЕ
template <typename S, typename D>
typename std::enable_if<(sizeof(S)<sizeof(D)), S>::type convert (S a)
{ return a << (sizeof(D) - sizeof(S)) * 8; }
template <typename S, typename D>
typename std::enable_if<(sizeof(S)>sizeof(D)), S>::type convert (S a)
{ return a >> (sizeof(S) - sizeof(D)) * 8; }
и пример рассылки тегов (осторожно для обоих: код не проверен)
template <typename S, typename D>
S convert (S a, std::true_type)
{ return a << (sizeof(D) - sizeof(S)) * 8; }
template <typename S, typename D>
S convert (S a, std::false_type)
{ return a >> (sizeof(S) - sizeof(D)) * 8; }
template <typename S, typename D>
S convert (S a)
{ return convert<S, D>(a, std::integral_constant<bool, (sizeof(S)<sizeof(D))>{}); }