Lambda函数作为基类 [英] Lambda functions as base classes
问题描述
使用Lambdas进行游戏我发现了一个我不能完全理解的有趣的行为。
假设我有一个 struct Overload
来源于2个模板参数,并且有一个使用F1 :: operator();
子句。
现在如果我从两个函数派生我只能访问F1的操作符()(如我所料)
如果我从两个Lambda函数派生,这不再。真:我可以从F2访问操作()太
的#include<&iostream的GT;
//我使用g ++编译(GCC)4.7.2 20121109(红帽4.7.2-8)
//
// g ++的-Wall -std = C + +11 -g main.cc
// g ++ -Wall -std = c ++ 11 -DFUNCTOR -g main.cc
//
//或clang clang version 3.3(标签/ RELEASE_33 / rc2)
//
// clang ++ -Wall -std = c ++ 11 -g main.cc
// clang ++ -Wall -std = c ++ 11 -DFUNCTOR - g main.cc
//
//在Linux上localhost.localdomain 3.9.6-200.fc18.i686#1 SMP Thu Jun 13
// 19:29:40 UTC 2013 i686 i686 i386 i386 GNU / Linux盒
struct Functor1
{
void operator()(){std :: cout< Functor1 ::运算符()()\\\
; }
};
结构Functor2
{
void运算符()(INT){性病::法院LT&;< Functor2 ::运算符()(INT)\\\
}
};
:模板LT; typename的F1,F2 typename的GT&;
struct Overload:public F1,public F2
{
Overload()
:F1()
,F2(){}
超载(F1 X1,X2 F2)
:F1(X1)
,F2(X2){}使用F1 ::运算
();
};
:模板LT; typename的F1,F2 typename的GT&;
auto get(F1 x1,F2 x2) - >过载< F1,F2>
{
return Overload< F1,F2>(x1,x2);
}
int main(int argc,char * argv [])
{
auto f = get(Functor1(),Functor2 );
f();
#ifdef FUNCTOR
f(2); // this one not work IMHO correctly
#endif
auto f1 = get(
[](){std :: cout< operator()()\\\
;},
[](int){std :: cout<lambda2 :: operator()(int)\\\
;}
);
f1();
f1(2); // this one work but I do not know why
return 0;
}
标准规定:
lambda表达式的类型(也是闭包对象的类型)
$ b $
是一个唯一的未命名非联合类类型
我不能解释为什么会这样:任何人都可以 c
c> ,由lambda定义的类可以(在正确的情况下)提供到指向函数的指针的转换。 除了
运算符()
如果你添加一个捕获:
auto f1 = get(
[](){std :: cout<lambda1 :: operator ;},
[i](int){std :: cout<lambda2 :: operator()(int)\\\
;}
);
f1();
f1(2);
...转换为
指向函数的指针
trash9.cpp:在函数'int main(int,char **)':
trash9.cpp:49:9:error:没有匹配的调用'(Overload< main(int,char **)::& ()>,main(int,char **)::< lambda(int)>)(int)'
trash9.cpp:14:8:note:candidate is:
trash9.cpp:45:23:note:main(int,char **)::< lambda()
trash9.cpp:45:23:注意:候选人期望有0个参数,1个提供
Playing around with Lambdas I found an interesting behaviour that I do not fully understand.
Supose I have a
struct Overload
that derives from 2 template parameters, and has ausing F1::operator();
clause.Now if I derive from two functors I can only access the operator() of F1 (as I would expect)
If I derive from two Lambda Functions this is no longer true: I can access the operator() from F2 too.
#include <iostream> // I compiled with g++ (GCC) 4.7.2 20121109 (Red Hat 4.7.2-8) // // g++ -Wall -std=c++11 -g main.cc // g++ -Wall -std=c++11 -DFUNCTOR -g main.cc // // or clang clang version 3.3 (tags/RELEASE_33/rc2) // // clang++ -Wall -std=c++11 -g main.cc // clang++ -Wall -std=c++11 -DFUNCTOR -g main.cc // // on a Linux localhost.localdomain 3.9.6-200.fc18.i686 #1 SMP Thu Jun 13 // 19:29:40 UTC 2013 i686 i686 i386 GNU/Linux box struct Functor1 { void operator()() { std::cout << "Functor1::operator()()\n"; } }; struct Functor2 { void operator()(int) { std::cout << "Functor2::operator()(int)\n"; } }; template <typename F1, typename F2> struct Overload : public F1, public F2 { Overload() : F1() , F2() {} Overload(F1 x1, F2 x2) : F1(x1) , F2(x2) {} using F1::operator(); }; template <typename F1, typename F2> auto get(F1 x1, F2 x2) -> Overload<F1, F2> { return Overload<F1, F2>(x1, x2); } int main(int argc, char *argv[]) { auto f = get(Functor1(), Functor2()); f(); #ifdef FUNCTOR f(2); // this one doesn't work IMHO correctly #endif auto f1 = get( []() { std::cout << "lambda1::operator()()\n"; }, [](int) { std::cout << "lambda2::operator()(int)\n"; } ); f1(); f1(2); // this one works but I don't know why return 0; }
The standard states that:
The type of the lambda-expression (which is also the type of the closure object) is a unique, unnamed non- union class type
So every Lambda's types should be unique.
I cannot explain why this is so: can anyone shed some light on this please?
解决方案In addition to
operator()
, a the class defined by a lambda can (under the right circumstances) provide a conversion to a pointer to function. The circumstance (or at least the primary one) is that the lambda can't capture anything.If you add a capture:
auto f1 = get( []() { std::cout << "lambda1::operator()()\n"; }, [i](int) { std::cout << "lambda2::operator()(int)\n"; } ); f1(); f1(2);
...the conversion to
pointer to function
is no longer provided, so trying to compile the code above gives the error you probably expected all along:trash9.cpp: In function 'int main(int, char**)': trash9.cpp:49:9: error: no match for call to '(Overload<main(int, char**)::<lambda()>, main(int, char**)::<lambda(int)> >) (int)' trash9.cpp:14:8: note: candidate is: trash9.cpp:45:23: note: main(int, char**)::<lambda()> trash9.cpp:45:23: note: candidate expects 0 arguments, 1 provided
这篇关于Lambda函数作为基类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!