Câu hỏi của tôi là về phạm vi lambda cho các initializers thành viên tĩnh. Hãy xem xét các thử nghiệm sau đây:phạm vi lambda cho các thành viên tĩnh initializer
#include <functional>
#include <iostream>
struct S {
static const std::function<void(void)> s_func;
};
const std::function<void(void)> S::s_func = []() {
std::cout << "Hello from " << __PRETTY_FUNCTION__ << std::endl;
};
int main(void) {
S::s_func();
return 0;
}
gcc bắt đầu từ 4.8 định nghĩa các lambda trong phạm vi của S, vì vậy chương trình kết quả đầu ra một cái gì đó như thế này:
Hello from S::<lambda()>
(gcc-4.8.2 có một định nghĩa khác nhau cho __FUNCTION__
& macro Co, tuy nhiên các lambda vẫn được xác định trong phạm vi S
)
trong khi đó gcc-4.7 định nghĩa các lambda trong phạm vi toàn cầu, vì vậy chương trình đầu ra
Hello from <lambda()>
Có thể gcc mới hơn tuân thủ chuẩn hơn. Tuy nhiên tôi muốn hỏi liệu tiêu chuẩn có thực sự chỉ định khía cạnh này hay không hoặc nó có thể phụ thuộc vào việc triển khai thực hiện.
Cập nhật: vì @ user5434961 đề xuất rằng tất cả các macrođều giống nhau, nên tốt hơn là tránh chúng trong thử nghiệm tuân thủ tiêu chuẩn. Vì vậy, đây là ví dụ mà có thể được biên dịch nếu một trình biên dịch định nghĩa lambdas đó trong thời hạn S
phạm vi và phá vỡ biên soạn khác:
#include <functional>
#include <iostream>
struct S {
static const std::function<void(void)> s_func;
private:
static const int s_field;
};
const std::function<void(void)> S::s_func = []() {
std::cout << "Hello from S::s_func. S::s_field = " << S::s_field << std::endl;
};
const int S::s_field = 1;
int main(void) {
S::s_func();
return 0;
}
Tôi đoán bạn nên thay đổi 'S :: s_field' thành' s_field' trong ví dụ được cập nhật? Nếu không, tôi nghĩ nó luôn biên dịch bất kể phạm vi là gì. – Lingxi
Vâng, vì 'S :: s_field' là riêng tư, nó không thể được truy cập từ phạm vi toàn cầu nên mã không phá vỡ biên dịch trên GCC-4.7 thực sự – user3159253
Có, có. Tôi bỏ qua những điều riêng tư. – Lingxi