是否可以指定可选的返回类型并在未指定的情况下推导出它?

时间:2014-03-28 12:51:52

标签: c++ templates

我想要一个转换函数,它将一些算法应用于参数并返回转换后的结果。但是,它不一定要更改返回类型,所以我想给调用者提供省略返回类型规范的选项,让编译器从输入类型中推导出它。

(简体)示例:

template <typename Ret = In, typename In, typename Func>
Ret transform(const In& in, Func f)
{
    return f(in);
}

我想这样称呼它:

auto result = transform(inValue, transformation); // 1
auto differentResult = transform<DifferentType>(inValue, transformation); // 2

请记住,这是简化的。实际上,我将f向前传递到std::transformInRet类型是某种容器。因此,我无法使用f或其他魔法的结果来确定返回类型。当然,提供的示例不起作用,因为这

typename Ret = In, typename In

是非法的。如果我反过来这样做:

typename In, typename Ret = In

它将完全符合我想要的情况1.但是我必须为案例2指定输入类型:

auto differentResult = transform<InType, DifferentType>(inValue, transformation);

这主要是一个方便的问题,如果没有办法,那就这样吧。看来我需要某种尾随模板类型说明符:)

真实代码

template <typename Ret, typename In, typename Func>
Ret transform(const In& input, Func func)
{
    Ret output{};
    std::transform(std::cbegin(input), std::cend(input), std::inserter(output, std::end(output)), func);
    return output;
}

使用上面的表单我总是要指定一个返回类型。我只是想知道如果没有给出input的模板参数,是否有办法从Ret推导出它。

编辑:如果我提供两个重载,一个使用2个模板参数,另一个使用3,它可以工作。我仍然想知道是否只能使用一个函数来实现这一点。

1 个答案:

答案 0 :(得分:4)

类似于that的东西,带有简单的函数重载:

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>

template <typename T>
std::ostream& operator<<( std::ostream& os, std::vector<T> const & vec ) {
    for( auto & e : vec )
        os << e << " ";
    return os;
}

template <typename Ret, typename In, typename Func>
Ret transform_copy( In const& input, Func&& func) {
    Ret output{};
    std::transform( std::begin(input), std::end(input), std::inserter(output, std::end(output)), std::forward<Func>(func) );
    return output;
}

template <typename In, typename Func>
In transform_copy( In const& input, Func&& func) {
    return transform_copy<In,In,Func>(input, std::forward<Func>(func));
}

int main() {
    std::string str = "abc";

    auto r0 = transform_copy( str, [](char b) { return b+1;} );
    std::cout << r0 << "\n";

    auto r1 = transform_copy<std::vector<int>>( str, [](char b) { return b+1;} );
    std::cout << r1 << "\n";

    auto r2 = transform_copy<std::string>( r1, [](char b) { return b+1;} );
    std::cout << r2 << "\n";
}