Передача шаблонной функции в for_each

295
14 июня 2017, 02:43

Выдает ошибку при попытке передать в функцию for_each, третьим параметром, шаблон функции. Помогите разобраться.

#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
#include <iterator>
using namespace std;
template <typename T>
void display(T a){
     cout << a;
}
void main(){
     setlocale(0, "russian");
     ifstream in("text.txt");
     vector<int> vectr;
     int i;
     while(!in.eof()){
        in >> i;
        vectr.push_back(i);
     }
    for_each(vectr.begin(), vectr.end(), display);
    cout << endl;
    system("pause");
}

Компилятор пишет, что нельзя использовать шаблон функции в качестве параметра. Почему нельзя использовать? И как это обойти?

 `error C2896: '_Fn1 std::for_each(_InIt,_InIt,_Fn1)' : cannot use function 
  template 'void display(T)' as a function argument
  see declaration of 'display'
  error C2784: '_Fn1 std::for_each(_InIt,_InIt,_Fn1)' : could not deduce 
  template 
  argument for '_InIt' from 'std::_Vector_iterator<_Myvec>'
         with
         [
              _Myvec=std::_Vector_val<int,std::allocator<int>>
         ]
  algorithm(28) : see declaration of 'std::for_each'

`

Answer 1

Самая важная для вас часть ошибки звучит так:

could not deduce template argument for ...

Это означает, что компилятор не смог выполнить неявное выведения типа шаблонного параметра для void display<T>(T a). Надо ему немного в этом помочь:

for_each(vectr.begin(), vectr.end(), display<int>);

Теперь разберёмся, почему компилятор не смог вывести тип самостоятельно.

Дело в том, что сигнатура функции std::foreach объявлена слишком абстрактной:

template <class InputIterator, class Function>
    Function for_each (InputIterator first, InputIterator last, Function fn);

Тип функции никак не завязан на типе итераторов. В придачу, нет никакой опережающей проверки типа аргумента функтора Function на уровне шаблонного объявления. Вот из-за этой независимости компилятор и не знает, как соотнести Function с display<T>(). Будь метод объявлен так:

template <class InputIterator, class Ret>
    Function for_each (InputIterator first, InputIterator last, Ret(*fn)(std::iterator_traits<InputIterator>::value_type));

компилятор смог бы применить type deduction и подставить шаблонный аргумент функции: Ret(*)(std::iterator_traits<InputIterator>::value_type)Ret(*)(int)void(*)(int).

Но для подобных манёвров необходимо было бы определять шаблонные перегрузки для всех типов функторов (навскидку: свободные функции, методы классов и функциональные классы (те, которые с operator())). То есть ради возможности опустить <int> нам необходимо усложнить стандартную библиотеку.

READ ALSO
Добавить хеш git в исходный код

Добавить хеш git в исходный код

Как заставить Visual Studio автоматом при сборке присваивать макросу GIT_HASH значение хеша git, без использования дополнительных утилит/установки...

304
Странный конфликт jQuery и Google Chrome Api

Странный конфликт jQuery и Google Chrome Api

Столкнулся со странными поведением JQ и хрома, а именно, в консоль выдает следующие ошибки:

351
Управление обработчиком [требует правки]

Управление обработчиком [требует правки]

Есть обработчикbind, обрабатывает от scroll, как выполнять другие функции если: скроллишь вверх, вниз или не скроллишь

223