不能';t在我尝试使用“t”时推断模板参数;“地图”;功能 我想在C++中生成一个“map”函数,它使用函数和容器,并返回该容器,但是函数返回的元素类型,这些元素应该是将函数应用到容器参数元素的结果。

不能';t在我尝试使用“t”时推断模板参数;“地图”;功能 我想在C++中生成一个“map”函数,它使用函数和容器,并返回该容器,但是函数返回的元素类型,这些元素应该是将函数应用到容器参数元素的结果。,c++,templates,c++11,C++,Templates,C++11,例如,我们应该能够做到: map([](int i){return float(i + 1);}, vector<int> {1, 2, 3}); // vector<float> {2.0, 3.0, 4.0} map([](inti){返回浮点(i+1);},向量{1,2,3});//向量{2.0,3.0,4.0} 这是我尝试实现它的过程,但似乎我不完全理解模板编程: #包括 #包括 #包括 #包括 #包括 模板< typename函数, 模板类Contain

例如,我们应该能够做到:

map([](int i){return float(i + 1);}, vector<int> {1, 2, 3});  // vector<float> {2.0, 3.0, 4.0}
map([](inti){返回浮点(i+1);},向量{1,2,3});//向量{2.0,3.0,4.0}
这是我尝试实现它的过程,但似乎我不完全理解模板编程:

#包括
#包括
#包括
#包括
#包括
模板<
typename函数,
模板类ContainerT,
类型名ElemT,
类FunctionResultT=typename std::result\u of
>
ContainerT地图(
Function t func,
const ContainerT和container
){
容器结果容器;
用于(常量自动和元素:容器){
结果容器。推回(func(elem));
}
返回结果容器;
}
模板
T增加1(常数T和数字){
返回号码+1;
}
模板
标准::字符串编号字符串(常量T和编号){
返回std::to_字符串(数字);
}
int main(){
const auto theList=std::list{1.0,2.0,3.0,4.0,5.0};
for(常量自动&ele:map(numberToString,map(increaseByOne,theList))){

std::cout我发现了几个导致问题的因素。以下是我发现的内容列表:

  • 函数模板表示一个无限重载集。当您将其作为参数传入时,需要知道函数的类型。这意味着需要显式指定它的模板参数。也就是说,需要更改这些参数:

    map(numberToString, map(increaseByOne, theList)
    //  ^^^^^^^^^^^^^^      ^^^^^^^^^^^^^
    
    为此:

    map(numberToString<float>, map(increaseByOne<float>, theList)
    //                ^^^^^^^                   ^^^^^^^
    
    这意味着
    ContainerT
    只能接受一个模板参数。当编译器看到您正试图从
    std::list
    的实例中推断此类型时,它会发现模板参数的数量不匹配。然后类型推断失败。C++11具有可变参数包,您可以使用它们使
    ContainerT
    接受任意数量的模板参数:

    template<typename...> class ContainerT,
    
    但请注意,这将失败,因为
std::result_是一个模板,如果其模板参数是一个functor,则该模板仅提供一个
::type
成员。这基本上意味着如果该类具有重载的
操作符()
成员函数

您可以将
FunctionResultT
std::result\u设置为函数调用的默认类型,而不是使用
std::result\u。如下所示:

class FunctionResultT = decltype(std::declval<FunctionT>()(std::declval<ElemT>()));
class FunctionResultT=decltype(std::declval()(std::declval());
现在,这是我所做更改的结果:

template <
    typename FunctionT,
    template <typename...> class ContainerT,
    typename ElemT,
    class FunctionResultT = decltype(std::declval<FunctionT>()(std::declval<ElemT>()))
>
模板<
typename函数,
模板类ContainerT,
类型名ElemT,
类FunctionResultT=decltype(std::declval()(std::declval())
>
模板
OutputContainer映射(Fn-Fn,InputContainer-input\u容器){
输出容器输出;
用于(自动输入:输入容器(&i)
输出。推回(fn(i));
返回输出;
}

你似乎喜欢让生活变得复杂…不是每个容器都有
推回方法好的,我想至少对那些有推回方法的容器这样做。如果有办法让它更通用,那就更好了。这里的问题不是每个容器是否都有推回方法。我不知道如何编写map的声明正确。+1如果您还包括参数类型,那么最后一个可以使用
result\u of
,因为变量模板参数的正确方法可能并不明显。我非常喜欢Praetorian的改进。这里的问题是无法推导返回类型,但需要在编译时指定(
auto foo=map(func,bar);
不会编译,您需要
auto foo=map(func,bar);
)。这可能是一个优势-输出容器可能与输入容器具有不同的类型。
template<typename...> class ContainerT,
class FunctionResultT = typename std::result_of<FunctionT>::type
//                                                        ^^^^^^
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;
}