C++ 将lambda作为函数指针传递,该函数返回多态唯一\u ptr
我想传递一个非捕获lambda,它返回一个C++ 将lambda作为函数指针传递,该函数返回多态唯一\u ptr,c++,lambda,function-pointers,c++14,C++,Lambda,Function Pointers,C++14,我想传递一个非捕获lambda,它返回一个 std::unique_ptr,作为类型为std::unique_ptr(*)的函数指针() 但是,只有当我将lambda的返回类型显式声明为std::unique\u ptr时,这才有效 为什么我要显式地声明返回类型 没有这个额外的返回类型,为什么它对std::function有效 #包括 #包括 结构基{virtual~Base()=default;}; 派生结构:基{}; 结构失败RF2 { 使用Function=std::add\u po
std::unique_ptr
,作为类型为std::unique_ptr(*)的函数指针(
)
但是,只有当我将lambda的返回类型显式声明为std::unique\u ptr
时,这才有效
- 为什么我要显式地声明返回类型
- 没有这个额外的返回类型,为什么它对
有效李>std::function
#包括
#包括
结构基{virtual~Base()=default;};
派生结构:基{};
结构失败RF2
{
使用Function=std::add\u pointer\t;
FailsForF2(函数f){}
};
结构工程
{
使用Function=std::Function;
作品(功能f){}
};
std::unique_ptr fun(){return std::make_unique();}
int main()
{
自动f1=[](){return std::make_unique();};
自动f2=[](){return std::make_unique();};
自动f3=[]()->std::unique_ptr{return std::make_unique();};
工程x1(f1);
工程x2(f2);
工程x3(f3);
f2 x4(f1)的故障;
故障f2 x5(f2);
失效f2 x6(f3);
}
gcc错误:
main.cpp: In function 'int main()':
main.cpp:34:20: error: invalid user-defined conversion from 'main()::<lambda()>' to 'FailsForF2::Function {aka std::unique_ptr<Base> (*)()}' [-fpermissive]
FailsForF2 x5(f2);
^
main.cpp:26:17: note: candidate is: main()::<lambda()>::operator std::_MakeUniq<Derived>::__single_object (*)()() const <near match>
auto f2 = [](){return std::make_unique<Derived>();};
^
main.cpp:26:17: note: no known conversion from 'std::_MakeUniq<Derived>::__single_object (*)() {aka std::unique_ptr<Derived> (*)()}' to 'FailsForF2::Function {aka std::unique_ptr<Base> (*)()}'
main.cpp:10:4: note: initializing argument 1 of 'FailsForF2::FailsForF2(FailsForF2::Function)'
FailsForF2(Function f) {}
main.cpp:在函数“int main()”中:
main.cpp:34:20:错误:从“main()::”到“FailsForF2::Function{aka std::unique_ptr(*)()}”[-fppermissive]的用户定义转换无效
故障f2 x5(f2);
^
main.cpp:26:17:注意:候选对象是:main()::操作符std::\u MakeUniq::\u单个对象(*)()常量
自动f2=[](){return std::make_unique();};
^
main.cpp:26:17:注意:没有已知的从'std:_MakeUniq::u single_object(*)到'FailsForF2::Function{aka std::unique_ptr(*)的转换
main.cpp:10:4:注意:初始化'FailsForF2::FailsForF2(FailsForF2::Function)'的参数1
FailsForF2(函数f){}
TL;博士强>
失败是因为FailsForF2
不能隐式转换为std::unique_ptr(*)(
)李>std::unique_ptr(*)(
之所以有效,是因为Works
可以隐式转换为std::unique_ptr
(请参见末尾的标准引号)std::unique_ptr
lambda可隐式转换为具有相同返回类型和参数1的函数指针,因此三个lambda可分别转换为:
std::unique_ptr<Base> (*) ()
std::unique_ptr<Derived> (*) ()
std::unique_ptr<Base> (*) ()
当您显式指定lambda的返回类型时,您将更改lambda的call运算符的返回类型(实际上是与之关联的闭包类型,请参见末尾的引号),因此可以进行转换
另一方面,
std::function
没有此类约束-std::function的构造函数是模板化的,因此它可以接受任何可调用的:
template <typename F>
std::function(F &&f);
模板
std::函数(F&&F);
…只要以下各项有效2:
调用(f,std::forward(args)…,R)
1引用N4594第5.1.5/7节的标准内容(重点是我的):
不具有lambda捕获的非一般lambda表达式的闭包类型具有与C++语言链接(7.5)具有强>相同参数和返回类型< /强>的函数指针的转换函数 闭包类型的函数调用运算符。[……]
2 N4594的标准引用,§20.12.12.2/2: 如果表达式INVOKE(f,declval(),R)
被视为未赋值的操作数(第5条),则类型为f的可调用对象f可用于参数类型ArgTypes和返回类型R(20.12.2)
…和§20.12.2(重点是我的,1.1到1.6是关于指向成员函数的指针(或类似的),因此在这里不相关):
1定义调用(f,t1,t2,…,tN)
如下:
(1.x)-[…]
(1.7)f(t1,t2,…,tN)在所有其他情况下
2将调用(f,t1,t2,…,tN,R)
定义为静态强制转换(调用(f,t1,t2,…,tN)
),如果R为cv void,否则调用(f,t1,t2,…,tN)
隐式转换为R
除了Holt的答案之外,为了回答您的第一个问题:您不必显式地将返回类型指定为尾部返回类型。但是,由于您正在创建一个
唯一的\u ptr
,但需要一个唯一的\u ptr
,因此您应该返回后者并在函数中执行转换
所以,我相信,这是一种
auto f2 = [](){ return std::unique_ptr<Base>{new Derived()}; };
auto f2=[](){return std::unique_ptr{new Derived()};};
它也可以编译。不会
std::add\u pointer\t代码>是指向唯一\u ptr
的指针吗?请看,我可能不是这里的专家,但我可以猜到编译器在将唯一\u ptr
转换为指向唯一\u ptr
的指针时遇到问题,而将唯一\u ptr
转换为指向唯一\u ptr
的指针时可能会遇到问题implicitly@Hayt我使用std::add\u pointer\t代码>请注意右边的()
。那没关系。它可能与函数ptr(第一个是)和函数对象的不同行为有关,但我现在找不到任何与之相关的链接(与lambdas的组合有关。可能还有lambda到c函数ptr的转换)@m.s.这里没有例外的安全问题(但我同意通常你应该选择make_unique
),但是如果你需要,你可以std::unique\u ptr(std::make_unique())
(这基本上是f3
隐含的功能,或者std::function
版本)-但是如果你需要转换成函数指针,最好的方法是显式指定返回类型,如f3
中所示。
template <typename F>
std::function(F &&f);
INVOKE(f, std::forward<Args>(args)..., R)
auto f2 = [](){ return std::unique_ptr<Base>{new Derived()}; };