Uważam, że GCC jest niezgodny. N3092 §5.1.2/5 mówi
typ zamknięcia dla lambda-ekspresyjnych publicznego rolki dla obsługi funkcji (13.5.4), którego pa- Zastosowano cewniki i powrót typu są opisane przez lambda-expression's parametr-deklaracja-klauzula i odpowiednio - zwrotny typ. Ten operator wywołania funkcji jest zadeklarowane const (9.3.1) wtedy i tylko wtedy, gdy nie parametr deklaracja-klauzuli lambda ekspresji jest następnie zmienny.
więc wiele rzeczy o zamknięcie typu obiektu są zdefiniowane w implementacji, sama funkcja musi być zarejestrowany jako public
i musi być nonstatic member aby być const
.
EDIT: Program ten wskazuje, że operator()
jest funkcja składowa na GCC 4.6, który jest zasadniczo taki sam jak 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;
}
wyjściowa:
member of Z4mainEUlvE_, returns i takes i
EDIT: Wygląda na to, jedynym problemem jest to, że wskaźniki do niektórych operatorów telefonicznych zamknięcie nie pasuje ptmf wzorów szablonów. Rozwiązaniem jest zadeklarowanie wyrażenia lambda mutable
. Nie ma to znaczenia, jeśli nie ma przechwytywania i tylko (poza rozwiązaniem problemu) wydaje się zmieniać konstelację operatora połączenia.
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;
wyjściowa:
returns i takes i
member of Z4mainEUliE0_ , returns i takes i
member of Z4mainEUliE0_ , returns i takes i
Bez zmienny iz const, spectfun
nie drukuje podpisów dla jednego z dwóch ostatnich zapytaniami.
Czy nie byłoby to niezgodne z g ++, ponieważ korzysta z darmowych funkcji? – GManNickG
Tak, dla mnie brzmi to tak, jakby to GCC było źle. – jalf
@ Gman, jalf: Bah, selektywne przesłuchanie. Cóż, metoda GCC wiąże się z większą przyjaźnią ... ha! – Potatoswatter