Tôi tin rằng GCC không tuân thủ. N3092 §5.1.2/5 nói
Kiểu đóng cửa cho một lambda-biểu có inline hàm operator gọi công cộng (13.5.4) có eters param- và kiểu trả về là mô tả bằng mệnh đề khai báo tham số của lambda-expression và kiểu trả về theo sau tương ứng. Toán tử gọi hàm này là được khai báo const (9.3.1) nếu và chỉ khi mệnh đề khai báo tham số của lambda- expression không phải là tiếp theo là có thể thay đổi.
Vì vậy, trong khi nhiều điều về loại đối tượng đóng của là thực hiện xác định, chức năng riêng của mình phải là thành viên để được public
và phải là thành viên không tĩnh được const
.
EDIT: Chương trình này chỉ ra rằng operator()
là một chức năng thành viên trên GCC 4.6, cơ bản giống như 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;
}
đầu ra:
member of Z4mainEUlvE_, returns i takes i
EDIT: Dường như vấn đề duy nhất là con trỏ để khai thác cuộc gọi đóng cửa nhất định không phù hợp với mô hình mẫu ptmf. Cách giải quyết khác là khai báo biểu thức lambda mutable
. Điều này là vô nghĩa nếu không có nắm bắt và chỉ (ngoài việc sửa chữa vấn đề) dường như thay đổi const-ness của nhà điều hành cuộc gọi.
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;
đầu ra:
returns i takes i
member of Z4mainEUliE0_ , returns i takes i
member of Z4mainEUliE0_ , returns i takes i
Nếu không có thể thay đổi và với const, spectfun
không in chữ ký cho một trong hai câu hỏi cuối cùng.
Điều đó không làm cho g ++ trở nên không tương thích, vì nó sử dụng chức năng miễn phí? – GManNickG
vâng, âm thanh với tôi như nó là GCC đó là nhận được nó sai. – jalf
@Gman, jalf: Bah, nghe có chọn lọc. Vâng, phương pháp của GCC liên quan đến tình bạn nhiều hơn ... ha! – Potatoswatter