无法推断模板参数,因为我试图使"map"函数
Couldn't infer template argument in my attempt to make "map" function
我想在c++中创建一个"map"函数,它接受一个函数和一个容器,并返回该容器,但包含由函数返回的类型元素,这些元素应该是将函数应用于容器参数元素的结果。
例如,我们应该能够这样做:
map([](int i){return float(i + 1);}, vector<int> {1, 2, 3}); // vector<float> {2.0, 3.0, 4.0}
这是我的尝试实现它,但看起来像我不完全理解模板编程:http://ideone.com/zMYCVw
#include <iostream>
#include <functional>
#include <string>
#include <list>
#include <vector>
template <
typename FunctionT,
template <typename> class ContainerT,
typename ElemT,
class FunctionResultT = typename std::result_of<FunctionT>
>
ContainerT<FunctionResultT> map(
FunctionT func,
const ContainerT<ElemT>& container
){
ContainerT<FunctionResultT> resultContainer;
for (const auto& elem : container){
resultContainer.push_back(func(elem));
}
return resultContainer;
}
template <typename T>
T increaseByOne(const T& number){
return number + 1;
}
template <typename T>
std::string numberToString(const T& number){
return std::to_string(number);
}
int main(){
const auto theList = std::list<float> {1.0, 2.0, 3.0, 4.0, 5.0};
for (const auto& ele : map(numberToString, map(increaseByOne, theList))){
std::cout << ele << std::endl;
}
}
编译器错误:
file.cpp:39:48: error: no matching function for call to 'map'
for (const auto& ele : map(numberToString, map(increaseByOne, theList))){
^~~
file.cpp:13:29: note: candidate template ignored: couldn't infer template argument 'FunctionT'
ContainerT<FunctionResultT> map(
^
1 error generated.
我发现了导致问题的几个因素。以下是我的发现:
-
函数模板表示无限重载集。函数的类型需要在将其作为参数传递时知道。这意味着需要显式地指定它的模板参数。也就是说,这些需要修改:
map(numberToString, map(increaseByOne, theList) // ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^
:
map(numberToString<float>, map(increaseByOne<float>, theList) // ^^^^^^^ ^^^^^^^
-
std::list
接受多个模板参数。其余的都是默认的。当您将模板参数定义为:template<typename> class ContainerT,
意味着
ContainerT
只能接受一个模板参数。当编译器看到你试图从std::list
的实例中推断出这种类型时,它会看到模板参数的数量不匹配。然后类型演绎失败。c++ 11有可变参数包,你可以使用它们来使ContainerT
接受任意数量的模板参数:template<typename...> class ContainerT,
-
最后,您没有为
FunctionResultT
提供type
。你可以在这里设置:class FunctionResultT = typename std::result_of<FunctionT>::type // ^^^^^^
但是注意,这将失败,因为
std::result_of
是一个模板,只有当其模板实参是函子时才提供::type
成员。这基本上意味着,如果它是一个具有重载operator()
成员函数的类。您可以将
FunctionResultT
默认为函数调用的类型,而不是使用std::result_of
。这样的:class FunctionResultT = decltype(std::declval<FunctionT>()(std::declval<ElemT>()));
现在这是我所做的更改的结果:
template <
typename FunctionT,
template <typename...> class ContainerT,
typename ElemT,
class FunctionResultT = decltype(std::declval<FunctionT>()(std::declval<ElemT>()))
>
template<class OutputContainer, class InputContainer, typename Fn>
OutputContainer map(Fn fn, InputContainer input_container){
OutputContainer output;
for(auto&i:input_container)
output.push_back(fn(i));
return output;
}
相关文章:
- 如何导出包含具有"std::unique_ptr"值的"std::map"属性的
- std::map<struct,struct>::find 找不到匹配项,但是如果我循环通过 begin() 到 end(),我在那里看到匹配项
- 使用一个考虑到std::map中键值的滚动或换行的键
- C++ Windows 驱动程序MSB3030无法复制该文件,因为它找不到
- 为什么 const std::p air<K,V>& 在 std::map 上基于范围的 for 循环不起作用?
- 允许从 std::map 的密钥窃取资源?
- 有没有办法对std::unordered_set、std::unrdered_map、std::set、std::map
- 将重物插入std::map
- 使用通用值初始化 std::map,不重复
- 仅包含可移动 std::map 的类的移动构造函数不起作用
- 我可以在这里替换什么,因为我不能在 C# 中使用隐式变量的 lambda 函数?
- C++:当所有条目都保证是唯一时,替代 std::map
- 使用模板化的键类型定义 std::map,该键类型基于作为参数接收的函数
- 如果 KEY 是 std::list 或 std::vector 而不是值,那么 std::map 的默认行为是什么?
- 使用字符数组作为 Map 中的键
- C++如何创建 std::map
- C++ equivalent to Java Map getOrDefault?
- 程序无法启动,因为缺少 libmpc-3.dll
- 当我使用 std::map 从文件中读取值时,该值会随之",",因为键和值用逗号分隔
- 无法推断模板参数,因为我试图使"map"函数