Ответ 1
Я считаю, что GCC несовместим. N3092 §5.1.2/5 говорит
Тип замыкания для лямбда-выражение имеет общедоступную встроенную оператор функции вызова (13.5.4) параметры и тип возврата описываемых лямбда-выражениями параметр-объявление-предложение и trailing-return-type соответственно. Этот оператор вызова функции объявленный const (9.3.1) тогда и только тогда, когда лямбда-выражения Параметр-выражение-предложение не с последующим изменением.
Таким образом, хотя многие вещи о типе объекта замыкания определяются по реализации, сама функция должна быть членом public
и должна быть нестатическим членом, чтобы быть const
.
EDIT: Эта программа указывает, что 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
EDIT: Похоже, единственная проблема заключается в том, что указатели на некоторые операторы вызова замыкания не соответствуют шаблонам шаблонов ptmf. Обходным путем является объявление лямбда-выражения 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 и с константой spectfun
не печатает подписи для любого из двух последних запросов.