How*_*ard 10 c++ lambda variadic-templates c++17
关于将lambda转换为std::functions 有关的SO有几个问题,但我还没有看到一个使用参数包作为参数列表的问题.这似乎打破了我的g ++版本(7.1.1-4),可能它不受支持.这是合法的c ++ 17(按标准)吗?如果没有,为什么?
#include <functional>
template <typename TReturn, typename ... TArgs>
void Functor(std::function<TReturn (TArgs...)> f) {}
int main(int argc, char * argv[]) {
    auto x = [] (int a, int b) { return a * b; };
    Functor<int, int, int>(x);
    return 0;
}
上面的代码将无法编译,因为它类型扣除失败.显然明确打字x的std::function<int (int, int)>,而不是使用auto使错误消失.但这不允许我Functor按照我的意愿传递r值.我还想通过使用函数类型的另一个模板参数来放弃任何类型安全性.
我真正不明白的是为什么上面的代码无法编译,但下面的代码很好并且有效:
#include <functional>
template <typename TReturn, typename TArgA, typename TArgB>
void Functor(std::function<TReturn (TArgA, TArgB)> f) {}
int main(int argc, char * argv[]) {
    auto x = [] (int a, int b) { return  a * b; };
    Functor<int, int, int> (x);
    return 0;
}
eca*_*mur 12
问题是编译器不知道你打算int, int成为整体TArgs,因此试图推断出TArgs参数的其余部分f.
例如,这将是有效的:
Functor<int, int, int>(std::function<int(int, int, char, float)>{});
// TArgs := {int, int, [...]                       char, float}
因此,您需要指示编译器不要尝试推断其余部分TArgs.例如,你可以写:
(*Functor<int, int, int>)(x);
或者您可以Functor使用未分解的签名编写Sig:
template <Sig>
void Functor(std::function<Sig> f) {}
或者您可以在非推导的上下文TArgs中包含参数的使用f:
template <typename TReturn, typename ... TArgs>
void Functor(std::function<std::conditional_t<false, void, TReturn (TArgs...)>> f) {}
这失败了:
#include <functional>
template <typename TReturn, typename ... TArgs>
void Functor(std::function<TReturn (TArgs...)> f) {}
int main(int argc, char * argv[]) {
    auto x = [] (int a, int b) { return a * b; };
    Functor<int, int, int>(x);
    return 0;
}
因为你没有指明整个TArgs...是{int, int}.你正在做的是指定前两种类型{int, int}.实际上,通过提供这三种类型,我们将演绎问题转化为:
template <typename ... TArgs>
void Functor(std::function<int(int, int, TArgs...)> f) {}
int main(int argc, char * argv[]) {
    auto x = [] (int a, int b) { return a * b; };
    Functor(x);
    return 0;
}
这不能编译,因为lambda不是std::function(或从一个派生而来),这与你在没有提供任何类型的情况下无法调用它的原因相同.
非变量版本没有这个问题,因为你已经提供了所有类型.
但实际上,你想要的是:
template <typename F>
void Functor(F ) {}
这不会失去任何类型的安全性.它正在使用std::function丢失类型信息,因为该类模板存在以键入erase.