Ошибка типа в шаблонной функции - PullRequest
2 голосов
/ 09 декабря 2010

Возможно, еще один тупой вопрос, который возник в результате моего изучения плохой книги по С ++ (я собираюсь исправить это).

Я играл с sstream и попробовал следующую функцию:

template <class num> num fromString(const std::string& str) {
  std::istringstream ss(str);
  num temp;
  ss >> temp;
  return temp;
}

Когда я называю это как:

int i = fromString<int>("123");

, все работает нормально.Но если я назову это так:

int i = fromString("123");

Я получил ошибку компиляции:

error: no matching function for call to ‘fromString(std::string&)’

Я думал, что компилятор поймет, что если я присваиваю значение intтогда я должен говорить о fromString<int>, но, похоже, дело не в этом.

Я что-то упустил?Должен ли я всегда указывать тип шаблонной функции?Или только когда тип шаблона является типом возврата?Или просто, когда тип шаблона не может быть определен типами входов?

Ответы [ 3 ]

9 голосов
/ 09 декабря 2010

Нет, компилятор не может вывести параметры шаблона только из возвращаемого типа.Вы должны быть конкретны, как и изначально:

int i = fromString<int>("123");

Одна из причин, почему компилятор не может сделать вывод в этом случае, заключается в том, что ряд типов может быть преобразован в int.Например:

class Gizmo
{
public:
  operator int() const;
};

Как компилятор узнает, что в этом случае не следует создавать экземпляр fromString<Gizmo>()?

3 голосов
/ 10 декабря 2010

Вы можете получить этот эффект с помощью простого трюка.

#include <sstream>
#include <string>
using namespace std;

struct from_string {
    string str;
    from_string(const string& s) : str(s) { }
    template <typename T>
    operator T() const {
        T ret;
        stringstream ss(str);
        ss >> ret;
        return ret;
    }
}

int main() {
    string s("1234");
    int a = from_string(s);
    return 0;
}
1 голос
/ 10 декабря 2010

В дополнение к тому, что Джон сказал о том, что это так называемый «не выводимый контекст», иногда можно обойти подобные вещи, предоставив фиктивный параметр типа шаблона:

#include <sstream>
#include <string>

template <typename T>
T from_string(const std::string& s, const T& /*dummy*/)
{
    std::stringstream ss;
    ss << s;
    T t;
    ss >> t;
    return t;
}

int main()
{
    std::string s = "23";
    int i = from_string(s, i);
    return 0;
}

Это помогает компилятору определить тип и избавит вас от необходимости явно указывать его. Это особенно полезно, когда имя переменной хорошее и короткое, как в примере выше.

...