Tại sao không loại bỏ thông số hoạt động trên các chức năng?


38

Chạy vào một cái gì đó kỳ lạ khi thực hiện một số mẫu siêu lập trình vào ngày khác. Về cơ bản, nó đi đến khẳng định này không (như tôi mong đợi) đi qua.

static_assert(std::is_same_v<void(), std::remove_reference_t<void()&>>);

Lúc đầu, tôi nghĩ rằng tôi đã mắc một lỗi cú pháp khi xác định tham chiếu hàm, nhưng xác nhận này đã vượt qua, cho thấy đó không phải là trường hợp.

static_assert(std::is_same_v<void()&, void()&>);

Tôi cũng đã cố gắng remove_referencetự thực hiện sao chép nguồn từ cppreference nhưng điều đó cũng không hiệu quả. Chuyện gì đang xảy ra ở đây?

Câu trả lời:


42

Chào mừng bạn đến với thế giới của các loại chức năng đáng ghét.

void() &không một tham chiếu đến void(). Cách đánh vần đó sẽ là void(&)()(mà nếu bạn remove_reference_t, bạn sẽ nhận được trở lại void()- đó là remove_reference_t thực hiện làm việc trên tài liệu tham khảo chức năng, nếu những gì bạn cung cấp cho nó thực sự là một tài liệu tham khảo để loại chức năng).

Điều void() &thực sự đề cập đến là loại hàm thành viên đủ điều kiện tham chiếu sau khi bạn loại bỏ lớp. Đó là:

struct C {
    void f() &;
};

Các loại &C::fvoid (C::*)() &. Nhưng tất cả các con trỏ tới các thành viên có thể được viết như T C::*đối với một số loại T, và trong trường hợp này, loại Tsẽ làvoid() & .

Xem thêm P0172 .


3
Ai đó nên tạo một câu hỏi chính tắc cho các loại chức năng gớm ghiếc.
Brian

Wow, C ++ không bao giờ làm tôi ngạc nhiên ngay cả khi tôi đã học và sử dụng nó trong gần 10 năm.
Kelvin Hu

13

Loại bạn có không phải là tham chiếu đến hàm, mà là hàm có vòng loại tham chiếu .

static_assert(std::is_same_v<void()&, void()&>);
static_assert(!std::is_same_v<void()&, void(&)()>);
static_assert(std::is_same_v<void(&)(), void(&)()>);
static_assert(std::is_same_v<void(), std::remove_reference_t<void(&)()>>);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.