8

我目前正在开发一个链接函数对象的库。

我正在创建一个函数模板,它接受一个可调用对象(目前是 std::function),并根据函数的输出和输入类型进行参数化。这是我定义的简化版本:

template <typename In, typename Out>
std::vector<Out> process(std::vector<In> vals, std::function< Out(In) > func)
{
    // apply func for each value in vals
    return result;
}

我遇到的问题是使用情况。似乎当我传递一个 lambda 时,编译器无法正确推断出类型,因此抱怨该函数不存在:

std::vector<string> strings;
// does NOT compile
auto chars = process(strings,
        []( std::string s ) -> char
        {
            return s[0]; // return first char
        }
);

如果我将 lambda 显式包装在 中std::function,则程序将编译:

std::vector<string> strings;
// DOES compile
auto chars = process(strings,
        std::function< char(std::string) >(
        []( std::string s ) -> char
        {
            return s[0]; // return first char
        })
);

我还没有测试过传递函数指针或函数对象,但如果我不直接传递显式对象,编译器似乎很难推断出Inand参数。Outstd::function

我的问题是:有没有办法解决这个问题,这样我就可以推断出可调用对象的输入/返回类型,而无需在调用站点明确提及它们?

也许在函数类型而不是输入/返回类型上参数化模板?本质上,我需要推断任意可调用对象的Inand类型。模板函数的返回类型Out可能是某种auto/技巧?decltype

谢谢你。

4

2 回答 2

9

我认为您可以做的是创建一个中间返回类型推导函数,用于decltype确定要传递给实际函数对象的参数:

template <typename Out, typename In>
std::vector<Out> process_intern(std::vector<In> vals, std::function< Out(In) > func)
{
    // whatever
}

template <typename In, typename Func>
auto process(std::vector<In> vals, Func func) -> std::vector<decltype(func(vals[0]))>
{
    return process_intern<decltype(func(vals[0]))>(vals, func);
}

当然,您可能需要考虑process()直接实现逻辑,除非有理由键入擦除函数类型。

于 2012-12-06T22:58:06.877 回答
8

有没有办法解决这个问题,这样我就可以推断出可调用对象的输入/返回类型,而无需在调用站点明确提及它们?

否。模板参数推导不考虑用户定义的转换。编译器必须提出InandOut使得参数的类型和参数的类型必须(几乎)完全匹配,但在这种情况下它们永远不会匹配。

也许在函数类型而不是输入/返回类型上参数化模板

是的,这就是通常所做的(例如,看看标准库算法)

于 2012-12-06T22:41:19.697 回答