【问题标题】:Compiler does not deduce template parameters (map std::vector -> std::vector)编译器不推导出模板参数(映射 std::vector -> std::vector)
【发布时间】:2014-12-27 05:04:43
【问题描述】:

我有以下模板。

template<typename T, typename U>
std::vector<U> map(const std::vector<T> &v, std::function<U(const T&)> f) {
    std::vector<U> res;
    res.reserve(v.size());
    std::transform(std::begin(v), std::end(v), std::end(res), f);
    return res;
}

当我在我的代码中使用它时,我指定了模板参数。为什么编译器不能为我推断出这个?我必须如何更改我的模板定义才能使其正常工作?

vector<int> numbers = { 1, 3, 5 };

// vector<string> strings = map(numbers, [] (int x) { return string(x,'X'); });

vector<string> strings = map<int, string>(numbers, [] (int x) { return string(x,'X'); });

可运行代码:http://ideone.com/FjGnxd

本题原代码来自这里:The std::transform-like function that returns transformed container

【问题讨论】:

    标签: c++ templates c++11 vector std


    【解决方案1】:

    您的函数需要一个 std::function 参数,但您使用 lambda 表达式调用它。两者不是同一类型。 lambda 可转换std::function,但模板参数推导需要完全匹配并且不考虑用户定义的转换。因此扣分失败。

    如果您实际上将std::function 传递给map(),则扣除确实有效。

    std::function<string(int const&)> fn = [] (int x) { return string(x,'X'); };
    vector<string> strings = map(numbers, fn);
    

    Live demo


    避免指定模板参数的一种可能解决方法是修改函数以接受任何类型的可调用对象,而不是std::function 对象。

    template<typename T, typename Func>
    std::vector<typename std::result_of<Func(T)>::type>
        map(const std::vector<T> &v, Func f) {
            // ...
        }
    

    同样想法的另一个版本,使用decltypedeclval而不是result_of

    template<typename T, typename Func>
    std::vector<decltype(std::declval<Func>()(std::declval<T>()))>
        map(const std::vector<T> &v, Func f) {
            // ...
        }
    

    最后,使用尾随返回类型

    template<typename T, typename Func>
    auto map(const std::vector<T> &v, Func f) 
      -> std::vector<decltype(f(v[0]))> {
            // ...
        }
    

    Live demo

    【讨论】:

    • 通常,typename std::result_of&lt;Func(T)&gt;::type 出现在map 函数内的多个位置。你不能 typedef 它使它更短,但他们是一种为它创建别名的方法,所以没有重复?
    • @Ferenc 如果你有 C++14,可以简写为std::result_of_t&lt;Func(T)&gt;。或者你可以自己写template&lt;typename T&gt; using result_of_t = typename result_of&lt;T&gt;::type;
    猜你喜欢
    • 1970-01-01
    • 2014-05-12
    • 2019-11-17
    • 2015-01-04
    • 1970-01-01
    • 2016-02-19
    • 1970-01-01
    • 1970-01-01
    • 2022-08-05
    相关资源
    最近更新 更多