#templates
#c #шаблоны
Вопрос:
Я создаю функцию Fold, которая может принимать разные классы, например, Sum, которые определяют тип выполняемой операции.
#include <iostream>
#include <vector>
#include <list>
template <typename T>
struct Sum {
public:
auto operator() (T init, std::list<int>::const_iterator first,
std::list<int>::const_iterator last) {
for (auto it = first; it != last; it) {
init = *it;
}
return init;
}
};
template <typename Iterat, typename T, typename Operator>
T Fold(Iterat first, Iterat last, T init, Operator func) {
return func(init, first, last);
}
int main() {
std::list<int> a{1, 2, 3, 6};
std::cout << Fold(a.cbegin(), a.cend(), 0, Sum()) << std::endl;
return 0;
}
Однако, когда я запустил код, я получил ошибку «нет жизнеспособного конструктора или руководства по выводу для вывода аргументов шаблона из ‘Sum'»
Ошибка может быть устранена двумя способами:
- Если я использую «int» вместо «template T» в сумме классов.
- Если я укажу в main() тип, который я хочу использовать, например:
Fold(a.cbegin(), a.cend(), 0, Sum<int>())
Есть ли другие способы что-то сделать с этой ошибкой? Ни одно из двух решений, которые я показал выше, не подходит для моей задачи
Ответ №1:
Аргументы шаблона выводятся из аргументов (функции). Поскольку Sum
у него нет аргументов, аргументы шаблона не могут быть выведены. Это объясняется здесь .
Однако не все потеряно. Sum
, как класс, не использует параметры шаблона. Только operator()
метод делает. Таким образом, вы можете поместить шаблон только в operator()
метод и оставить Sum
как класс, не являющийся шаблоном.
Например:
struct Sum {
public:
template <typename T>
auto operator() (T init, std::list<int>::const_iterator first,
std::list<int>::const_iterator last) {
for (auto it = first; it != last; it) {
init = *it;
}
return init;
}
};
Я бы также зашел так далеко, что создал шаблон итератора, как вы сделали с Fold . Полный пример кода с некоторыми дополнительными примерами использования:
#include <functional>
#include <iostream>
#include <list>
#include <vector>
struct Sum {
public:
template <typename T, typename Iterat>
auto operator() (T init, Iterat first, Iterat last) {
for (auto it = first; it != last; it) {
init = *it;
}
return init;
}
};
template <typename Iterat, typename T, typename Operator>
T Fold(Iterat first, Iterat last, T init, Operator func) {
return func(init, first, last);
}
int main() {
std::list<int> a{1, 2, 3, 6};
std::cout << Fold(a.cbegin(), a.cend(), 0, Sum()) << std::endl;
// init is a float. While the iterators return int.
std::cout << Fold(a.cbegin(), a.cend(), 0.5 , Sum()) << std::endl;
std::list<std::string> b{"1", "2", "3", "6"};
std::cout << Fold(b.cbegin(), b.cend(), std::string(""), Sum()) << std::endl;
return 0;
}