Ни один экземпляр шаблона функции не соответствует списку аргументов, типы аргументов: (std :: string, CommandLineArgumentTypes) - PullRequest
0 голосов
/ 01 августа 2020

У меня есть шаблон функции, который принимает значения std::string и enum, описывающие тип данных, содержащихся в строке. Он преобразует строку и возвращает std::string, int, unsigned int или bool в зависимости от значения enum.

template <typename T> T parseInput(std::string &input, CommandLineArgumentTypes &type) {
    switch (type) {
        case CommandLineArgumentTypes::String :
            return input;
        case CommandLineArgumentTypes::Int :
            if (int value = std::stoi(input)) {
                return value;
            }

            if (input.size() > 1) {
                if (input[0] == "0" && input[1] == "x") {
                    if (int value = std::stoi(input.substr(1, input.size() - 2))) {
                        return value;
                    }
                }
            }

            return NULL;
        case CommandLineArgumentTypes::UInt :
            return (unsigned int)std::stoi(input);
        case CommandLineArgumentTypes::Flag :
            return true;
    }
}

Когда я вызываю шаблон функции

parseInput(arg, type);

, где arg - строка, а type - CommandLineArgumentTypes, я получаю сообщение об ошибке

no instance of function template matches the argument list, argument types are: (std::string, CommandLineArgumentTypes).

Как получить шаблон для определения типа возвращаемого значения, почему эта ошибка возникает, когда аргументы соответствуют списку аргументов, и как это лучше сделать?

1 Ответ

5 голосов
/ 01 августа 2020

Я вижу две проблемы:

  1. аргумент шаблона T не выводится из типа аргументов (input и type).

Я понимаю, что вы намерены вывести его из значения типа, но это просто не работает в C ++.

Вы должны явно указать это, вызвав функцию ; например

 parseInput<bool>(arg, type);
ваша функция имеет разные return s с разными типами. И они несовместимы.

До C ++ 17 (до if constexpr) это невозможно.

В C ++ 17 это можно сделать, ( с if constexpr, а не с switch), но только если тест основан на известном значении времени компиляции.

Итак, если вы передадите type в качестве параметра шаблона (если вы знаете его значение, скомпилируйте -time, очевидно) вы можете написать что-то как (внимание: код не протестирован)

template <CommandLineArgumentTypes type>
auto parseInput (std::string &input)
 {
   if constexpr ( CommandLineArgumentTypes::String == type )
       return input;
   else if constexpr ( CommandLineArgumentTypes::Int == type )
    {
      // do something else
    }
   else if constexpr ( CommandLineArgumentTypes::UInt == type )
      return (unsigned int)std::stoi(input);
   else if constexpr ( CommandLineArgumentTypes::Flag == type )
      return true;
   // else ?
}

Вызов становится, например,

 parseInput<CommandLineArgumentTypes::UInt>(arg);

, но, повторяю, это может работать только если аргумент шаблона (старый type) известен типом компиляции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...