Sum*_*ant 15 c++ lambda traits c++11
我发现两个编译器(g ++ 4.5,VS2010 RC)之间存在一些不一致的方式,它们将lambdas与类模板的部分特化相匹配.我试图为lambdas实现类似boost :: function_types的东西以提取类型特征.请查看此内容以获取更多详
在g ++ 4.5中,operator()lambda 的类型看起来像一个独立函数(R(*)(...)),而在VS2010 RC中,它看起来像一个成员函数(R( C::*)(...)).所以问题是编译器编写者可以自由地解释他们想要的任何方式吗?如果没有,哪个编译器是正确的?请参阅以下详细信息.
template <typename T>
struct function_traits
: function_traits<decltype(&T::operator())>
{
// This generic template is instantiated on both the compilers as expected.
};
template <typename R, typename C>
struct function_traits<R (C::*)() const> { // inherits from this one on VS2010 RC
typedef R result_type;
};
template <typename R>
struct function_traits<R (*)()> { // inherits from this one on g++ 4.5
typedef R result_type;
};
int main(void) {
auto lambda = []{};
function_traits<decltype(lambda)>::result_type *r; // void *
}
Run Code Online (Sandbox Code Playgroud)
这个程序在g ++ 4.5和VS2010上编译,但实例化的function_traits是不同的,如代码中所述.
我认为 GCC 不合规。N3092 \xc2\xa75.1.2/5 说
\n\n\nlambda 表达式的闭包类型具有公共内联函数调用运算符 (13.5.4),其参数和返回类型由 lambda 表达式\xe2\x80\x99s\n 描述分别为参数声明子句和\n 尾随返回类型。\n 当且仅当\n lambda 表达式\xe2\x80\x99s\n 参数时,此函数调用运算符\n 被声明为const (9.3.1) -declaration-clause 后面不是可变的。
\n
因此,虽然关于闭包对象类型的许多事情都是实现定义的,但函数本身必须是 be 的成员,public并且必须是非静态成员const。
编辑:该程序表明这operator()是 GCC 4.6 上的成员函数,本质上与 4.5 相同。
#include <iostream>\n#include <typeinfo>\nusing namespace std;\n\ntemplate< class ... > struct print_types {};\n\ntemplate<> struct print_types<> {\n friend ostream &operator<< ( ostream &lhs, print_types const &rhs ) {\n return lhs;\n }\n};\n\ntemplate< class H, class ... T > struct print_types<H, T...> {\n friend ostream &operator<< ( ostream &lhs, print_types const &rhs ) {\n lhs << typeid(H).name() << " " << print_types<T...>();\n return lhs;\n }\n};\n\ntemplate< class T >\nstruct spectfun {\n friend ostream &operator<< ( ostream &lhs, spectfun const &rhs ) {\n lhs << "unknown";\n return lhs;\n }\n};\n\ntemplate< class R, class ... A >\nstruct spectfun< R (*)( A ... ) > {\n friend ostream &operator<< ( ostream &lhs, spectfun const &rhs ) {\n lhs << "returns " << print_types<R>()\n << " takes " << print_types<A ...>();\n return lhs;\n }\n};\n\ntemplate< class C, class R, class ... A >\nstruct spectfun< R (C::*)( A ... ) > {\n friend ostream &operator<< ( ostream &lhs, spectfun const &rhs ) {\n lhs << "member of " << print_types<C>() << ", " << spectfun<R (*)(A...)>();\n return lhs;\n }\n};\n\ntemplate< class T >\nstruct getcall {\n typedef decltype(&T::operator()) type;\n};\n\nint main() {\n int counter = 0;\n\n auto count = [=]( int ) mutable { return ++ counter; };\n\n cerr << spectfun< getcall<decltype(count)>::type >() << endl;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n输出:
\n\nmember of Z4mainEUlvE_, returns i takes i\nRun Code Online (Sandbox Code Playgroud)\n\n编辑:看起来唯一的问题是指向某些闭包调用运算符的指针无法匹配 ptmf 模板模式。解决方法是声明 lambda 表达式mutable。如果没有捕获,并且仅(除了解决问题之外)似乎改变了调用运算符的常量性,那么这是毫无意义的。
template< class T >\nstruct getcall {\n typedef decltype(&T::operator()) type;\n static type const value;\n};\ntemplate< class T >\ntypename getcall<T>::type const getcall<T>::value = &T::operator();\n\nint main() {\n auto id = []( int x ) mutable { return x; };\n int (*idp)( int ) = id;\n typedef decltype(id) idt;\n int (idt::*idptmf)( int ) /* const */ = getcall< decltype(id) >::value;\n\ncerr << spectfun< decltype(idp) >() << endl;\ncerr << spectfun< decltype(idptmf) >() << endl;\ncerr << spectfun< getcall<decltype(id)>::type >() << endl;\nRun Code Online (Sandbox Code Playgroud)\n\n输出:
\n\nreturns i takes i \nmember of Z4mainEUliE0_ , returns i takes i \nmember of Z4mainEUliE0_ , returns i takes i \nRun Code Online (Sandbox Code Playgroud)\n\n不带 mutable 且带 const 时,spectfun不会打印最后两个查询中任何一个的签名。
| 归档时间: |
|
| 查看次数: |
1657 次 |
| 最近记录: |