从参数的返回类型中推断类型

wht*_*lnv 2 c++ gcc c++11 c++14

我理解模板不能从赋值中推断出类型,即

template <typename T>
T aFunction (int a) { /*...*/ }; // This obviously won't work
Run Code Online (Sandbox Code Playgroud)

而且很明显为什么.但这奏效:

template <typename T>
T aFunction (T a, T b) { return a + b; }; // a-ok
Run Code Online (Sandbox Code Playgroud)

原因T将从论证中推断出来.我想从中推断一下:

template <typename T>
T aFunction (std::function<T(int)> a) { return a(3);};
                           ^
                           |
  I specified it! ----------
Run Code Online (Sandbox Code Playgroud)

所以当使用时,函数应该做什么没有歧义:

std::function<double(int)> blah = [](int x){ return x / 2.0f; };
aFunction(blah);
Run Code Online (Sandbox Code Playgroud)

唉,编译器不会与我合作:

调用'aFunction'没有匹配的成员函数

候选模板被忽略:无法匹配'function'与'(lambda at file.hpp:274:16)'

有没有办法让这种情况发生?缺少模板特化(这是一个非常通用的类),或者是一个虚拟参数(我不是那么绝望).


PD:

完全披露:以上只是问题的简化,正是我需要的是:

template <typename T>
class MyStuff {

    template <typename ReturnType>
    MyStuff<ReturnType> aFunction(std::function<ReturnType(T)> a){ 
        /*for each stuff in MyStuff do a(stuff)*/ 
    }
}
Run Code Online (Sandbox Code Playgroud)

其中MyStuff包含类型的属性T和一堆inline函数,例如aFunction.

sky*_*ack 5

如评论中所述,这有效:

#include <functional>

template <typename T>
struct MyStuff {
    template <typename ReturnType>
    MyStuff<ReturnType> aFunction(std::function<ReturnType(T)> a){ 
        return {};
    }
};

int main() {
    MyStuff<int> stuff;
    std::function<double(int)> fn = [](int) { return 0.; };
    stuff.aFunction(fn);
}
Run Code Online (Sandbox Code Playgroud)

相反,这不起作用:

int main() {
    MyStuff<int> stuff;
    stuff.aFunction([](int) { return 0.; });
}
Run Code Online (Sandbox Code Playgroud)

而错误是问题中发布的错误:

注意:候选模板被忽略:无法匹配'function'与'(lambda at main.cpp:15:21)'

原因是类型推导仅适用于确切类型.不允许转换.在你的情况下,编译器应首先推导出lambda的所有返回类型,而不是将其转换为std::function某种方式,最后从使用lambda构造的函数中推导出函数的返回类型.
这不是类型推导的工作原理.

你可以用这样的东西解决它:

template <typename T>
struct MyStuff {
    template <typename F>
    auto aFunction(F &&f) -> MyStuff<decltype(std::forward<F>(f)(std::declval<T>()))> { 
        return {};
    }
};
Run Code Online (Sandbox Code Playgroud)

Coliru看到它.