как сделать условный оператор, чтобы игнорировать типы строк std::при использовании параметров шаблона?

#c

#c

Вопрос:

Я сталкиваюсь с проблемами, когда пытаюсь использовать эту operator () функцию в классе для строкового объекта вместо символа или числового типа данных. Я попробовал следующую реализацию , чтобы проверить, являются ли повторяющиеся данные a std::string , но функция по-прежнему возвращает ошибку при выполнении этой части кода:

 this-gt;current -= this-gt;range-gt;step;  

Это имеет смысл, смысл в том , что вы не можете выполнить эту операцию над a std::string , однако мой текущий метод создания исключения для строк работает не совсем правильно, он продолжает выбрасывать:

 error: no match for 'operator-=' (operand types are 'std::__cxx11::basic_stringlt;chargt;' and 'std::__cxx11::basic_stringlt;chargt;' this-gt;current -= this-gt;range-gt;step;  

Есть какие-нибудь идеи по лучшей реализации или, возможно, по-другому написать этот код?

 Iteratoramp; operator  () {  bool isStr = false;  std::string str = "s";   auto cmp = this-gt;range-gt;step;  if (typeid(cmp) == typeid(str)) { // check if the variable is a string  isStr = true;  }  if (this-gt;range-gt;stop gt; this-gt;range-gt;start || isStr) { // if increasing, or working w/ strings  this-gt;current  = range-gt;step;  return *this;  } else if (this-gt;range-gt;stop lt; this-gt;range-gt;start) { // if decreasing  if (!isStr) {  this-gt;current -= this-gt;range-gt;step;  }  }  return *this; }  

Ответ №1:

Как и ваш код, он не завершен и не будет компилироваться. Но при работе с кодом, который должен делать выбор в зависимости от типа, используйте конструкции времени компиляции! Используйте такие вещи, как «перегрузка», «шаблоны», «если constexpr», «SFINAE». Например :

 #include lt;type_traitsgt; #include lt;stringgt;  struct foo_t {  templatelt;typename type_tgt;  autoamp; operator  ()  {  if constexpr (std::is_same_vlt;type_t, std::stringgt;) // lt;== check types at compile time!  {  // working with strings we go only one way  current  = range-gt;step;  }  else  {  // if increasing  if (range-gt;stop gt; range-gt;start )  {   current  = range-gt;step;  }  else if (range-gt;stop lt; range-gt;start)   {   current -= range-gt;step;  }  }  return *this;  } };  

Ответ №2:

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

В C 17 и более поздних версиях вы можете использовать if constexpr для этого, например:

 #include lt;type_traitsgt;  Iteratoramp; operator  () {  if constexpr (std::is_same_vlt;decltype(range-gt;step), std::stringgt;) { // check if the variable is a string  current  = range-gt;step;  }  else if (range-gt;stop gt; range-gt;start) { // if increasing  current  = range-gt;step;  }  else if (range-gt;stop lt; range-gt;start) { // if decreasing  current -= range-gt;step;  }  return *this; }  

В более ранних версиях C вместо этого вам придется перегружать оператор с помощью SFINAE ( std::enable_if() и т. Д.) Или специализации шаблона, чтобы изолировать std::string версию оператора в отдельную реализацию.