Вывод типа для std :: string в функции шаблона не работает - PullRequest
3 голосов
/ 15 мая 2019

Я пытаюсь изучить шаблоны C ++. Одна функция в скрипте компилируется, в то время как похожая функция завершается ошибкой. Весь сценарий:

#include <string>
#include <vector>
using std::vector;

template <typename T>
void works(vector<int>& vi, vector<double>& vd, vector<T>& inp) {
    if (std::is_same<T, double>::value)
        vd.push_back(inp[0]);
    else if (std::is_same<T, int>::value)
        vi.push_back(inp[0]);
}

template <typename T>
void doesnt_work(vector<std::string>& vs, vector<double>& vd, vector<T>& inp) {
    if (std::is_same<T, double>::value)
        vd.push_back(inp[0]);
    else if (std::is_same<T, std::string>::value)
        vs.push_back(inp[0]);  // Line 18:  no matching member function
}

int main() {
    vector<double> d = {2, 3, 4};
    vector<double> doubles;
    vector<std::string> strings;
    vector<int> ints;
    doesnt_work(strings, doubles, d);  // Line 26: Comment out and script runs
    works(ints, doubles, d);
    return 0;
}

Функция works принимает два вектора vi и vd, содержащие int и double в качестве ссылок, а также третий вектор с элементами типа T. Затем я пытаюсь проверить тип из T и вставьте первый элемент вектора inp в vi или vd. Напротив, функция doesnt_work вызывает проблемы. Вместо принятия вектора int в качестве параметра он принимает вектор std::string. Я могу запустить весь скрипт, когда я закомментирую строку 26. В противном случае clang++ говорит мне, что

error: no matching member function for call to 'push_back'
        vs.push_back(inp[0]);

Кто-то любезно знает, что я делаю неправильно? Я не понимаю, почему программа не может получить доступ к функции push_back вектора vs.

1 Ответ

3 голосов
/ 15 мая 2019
template <typename T>
void now_works(vector<std::string>& vs, vector<double>& vd, vector<T>& inp) {
  if constexpr (std::is_same<T, double>::value)
    vd.push_back(inp[0]);
  else if constexpr (std::is_same<T, std::string>::value)
    vs.push_back(inp[0]);  // Line 18:  no error
}

ваша проблема в том, что все ветви компилируются, даже если они не запускаются.

if constexpr делает их компилированными, а затем отбрасывает их во время компиляции, игнорируя любые ошибки типа.

Код, который работал, все могло конвертировать, даже если он не был запущен, поэтому он компилировался.

Код, который не работал, преобразование, которое вы хотели исключить, является недопустимым, поэтому он потерпел неудачу во время компиляции.

Обратите внимание, что if constexpr работает только потому, что условие ветвления является константой времени компиляции, а также потому, что оно находится в шаблоне, и это предложение зависит от параметров шаблона, и недопустимый код такжезависит от параметров шаблона.

Если у вас еще нет if constexpr, потому что вы застряли на старой версии C ++, вы будете вынуждены делать что-то уродливое, например диспетчеризацию тегов или SFINAE с помощью вспомогательных функций иличто-то более загадочное.

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