我相信 GCC 是不合规的。N3092 §5.1.2/5 说
lambda 表达式的闭包类型具有公共内联函数调用运算符 (13.5.4),其参数和返回类型分别由 lambda 表达式的参数声明子句和尾随返回类型描述。当且仅当 lambda 表达式的 parameter-declaration-clause 后面没有 mutable 时,此函数调用运算符才被声明为 const (9.3.1)。
因此,虽然关于闭包对象类型的许多事情都是实现定义的,但函数本身必须是成员,public
并且必须是非静态成员const
。
编辑:这个程序表明它operator()
是 GCC 4.6 上的成员函数,它与 4.5 基本相同。
#include <iostream>
#include <typeinfo>
using namespace std;
template< class ... > struct print_types {};
template<> struct print_types<> {
friend ostream &operator<< ( ostream &lhs, print_types const &rhs ) {
return lhs;
}
};
template< class H, class ... T > struct print_types<H, T...> {
friend ostream &operator<< ( ostream &lhs, print_types const &rhs ) {
lhs << typeid(H).name() << " " << print_types<T...>();
return lhs;
}
};
template< class T >
struct spectfun {
friend ostream &operator<< ( ostream &lhs, spectfun const &rhs ) {
lhs << "unknown";
return lhs;
}
};
template< class R, class ... A >
struct spectfun< R (*)( A ... ) > {
friend ostream &operator<< ( ostream &lhs, spectfun const &rhs ) {
lhs << "returns " << print_types<R>()
<< " takes " << print_types<A ...>();
return lhs;
}
};
template< class C, class R, class ... A >
struct spectfun< R (C::*)( A ... ) > {
friend ostream &operator<< ( ostream &lhs, spectfun const &rhs ) {
lhs << "member of " << print_types<C>() << ", " << spectfun<R (*)(A...)>();
return lhs;
}
};
template< class T >
struct getcall {
typedef decltype(&T::operator()) type;
};
int main() {
int counter = 0;
auto count = [=]( int ) mutable { return ++ counter; };
cerr << spectfun< getcall<decltype(count)>::type >() << endl;
}
输出:
member of Z4mainEUlvE_, returns i takes i
编辑:看起来唯一的问题是指向某些闭包调用运算符的指针无法匹配 ptmf 模板模式。解决方法是声明 lambda 表达式mutable
。如果没有捕获并且只有(除了解决问题之外)似乎会改变调用运算符的常量,这是没有意义的。
template< class T >
struct getcall {
typedef decltype(&T::operator()) type;
static type const value;
};
template< class T >
typename getcall<T>::type const getcall<T>::value = &T::operator();
int main() {
auto id = []( int x ) mutable { return x; };
int (*idp)( int ) = id;
typedef decltype(id) idt;
int (idt::*idptmf)( int ) /* const */ = getcall< decltype(id) >::value;
cerr << spectfun< decltype(idp) >() << endl;
cerr << spectfun< decltype(idptmf) >() << endl;
cerr << spectfun< getcall<decltype(id)>::type >() << endl;
输出:
returns i takes i
member of Z4mainEUliE0_ , returns i takes i
member of Z4mainEUliE0_ , returns i takes i
如果没有 mutable 和 const,spectfun
则不会打印最后两个查询中的任何一个的签名。