Creo que GCC no cumple. N3092 §5.1.2/5 dice
El tipo de cierre para un lambda-expresión tiene una línea operador de llamada de función pública (13.5.4) cuya pará- metros y volver tipo son descrito por el lambda-expression's parameter-declaration-clause y trailing-return-type respectivamente. Este operador de llamada a función es declarado const (9.3.1) si y solo si lambda- expression parameter-declaration-clause no es seguido de mutable.
Así, mientras que muchas cosas sobre el tipo de objeto de cierre son definido por la implementación, la función en sí debe ser un miembro para ser public
y debe ser un miembro que no es para ser const
.
EDIT: Este programa indica que operator()
es una función miembro en GCC 4.6, que es esencialmente lo mismo que 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;
}
de salida:
member of Z4mainEUlvE_, returns i takes i
EDIT: Parece que el único problema es que los punteros a determinados operadores de llamadas de cierre no coinciden patrones plantilla pTMF. La solución consiste en declarar la expresión lambda mutable
. Esto no tiene sentido si no hay captura y solo (aparte de solucionar el problema) parece cambiar la constidad del operador de llamada.
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;
de salida:
returns i takes i
member of Z4mainEUliE0_ , returns i takes i
member of Z4mainEUliE0_ , returns i takes i
Sin la mutable y con la const, spectfun
no imprime firmas para cualquiera de las dos últimas consultas.
¿No haría eso que g ++ no cumpliera, ya que usa funciones libres? – GManNickG
Sí, me parece que es GCC el que está equivocando. – jalf
@Gman, jalf: Bah, audición selectiva. Bueno, el método de GCC implica más amistad ... ¡ja! – Potatoswatter