#c #templates #enums
#c #шаблоны #перечисления
Вопрос:
У меня есть шаблонная функция, которая работает нормально, если я не использую enum
тип аргумента as (здесь в сокращенной форме; он преобразует строку в тип anotjer с помощью stringstream
s):
template<typename T>
void section::getVal(std::string key,Tamp; var)
{
std::stringstream ss; ss.str(key);
ss>>var;
}
Теперь я хочу, чтобы эта функция работала с любым enum
, поэтому я попробовал
enum slimit {lower,higher,between,nolim};
template<typename T>
void section::getVal(std::string key,Tamp; var)
{
std::stringstream ss;
ss.str(key);
if(!std::is_enum<T>::value)
ss>>var;
else
{
int h;
ss>>h;
var=static_cast<T>(h);
}
}
К сожалению, это не компилируется
(error: no match for 'operator>>' (operand types are 'std::stringstream {aka std::__cxx11::basic_stringstream<char>}' and 'sensact::slimit')
ss>>var;)
Если я заменяю ss>>var;
на что-то, что не заботится о типе ( int n=0;
), он компилируется, и if-различие / is_enum
работает отлично, и блок else выполняется, если var
это enum
тип.
Итак, как я могу заставить ее работать и почему она не компилируется?
Ответ №1:
Хотя if
оператор выполняет только одну ветвь, он все равно компилирует все ветви. Поскольку код неверно сформирован в одной из ветвей, вы получаете сообщение об ошибке.
Если вы хотите условно скомпилировать некоторые ветки, вы можете использовать constexpr if
так:
if constexpr (!std::is_enum<T>::value)
ss >> var;
else
{
int h; // in general, std::underlying_type_t<T> instead of int,
// to allow for other enumeration types
ss >> h;
var=static_cast<T>(h);
}
Спасибо @Jarod42 за underlying_type
предложение в комментарии.
Комментарии:
1. Хорошо, но в OP нет тега C 17: вы должны указать, что
if constexpr
это доступно только начиная с C 17.2. ДА… может быть, пришло время признать, что C 17 (если не C 20) является ответственным.
3. @max66 Да, я пробовал это с парой решений C 20, но несколько пользователей жаловались: p, так что, возможно, пока нет. Но C 17 должен быть принят как минимум 🙂
4.
int
->std::underlying_type_t<T>
чтобы пойти дальше.5. @Jarod42 Привет, выглядит отлично, спасибо. Я узнал кое-что новое 🙂