Это легко объяснить на примере. Рассмотрим
struct Cat { void meow() { } };
struct Dog { void bark() { } };
и
template <typename T>
void pet(T x)
{
if(std::is_same<T, Cat>{}){ x.meow(); }
else if(std::is_same<T, Dog>{}){ x.bark(); }
}
Вызов
pet(Cat{});
pet(Dog{});
приведет к ошибке компиляции (пример wandbox) , потому что обе ветви оператора if
должны быть хорошо сформированы.
prog.cc:10:40: error: no member named 'bark' in 'Cat'
else if(std::is_same<T, Dog>{}){ x.bark(); }
~ ^
prog.cc:15:5: note: in instantiation of function template specialization 'pet<Cat>' requested here
pet(Cat{});
^
prog.cc:9:35: error: no member named 'meow' in 'Dog'
if(std::is_same<T, Cat>{}){ x.meow(); }
~ ^
prog.cc:16:5: note: in instantiation of function template specialization 'pet<Dog>' requested here
pet(Dog{});
^
Для изменения pet
для использования if constexpr
template <typename T>
void pet(T x)
{
if constexpr(std::is_same<T, Cat>{}){ x.meow(); }
else if constexpr(std::is_same<T, Dog>{}){ x.bark(); }
}
требуется только ветви, подлежащие анализу - только ветвь, которая соответствует условию, должна быть хорошо сформирована (пример wandbox) .
Отрывок
pet(Cat{});
pet(Dog{});
будет компилироваться и работать должным образом.