std :: is_constructible trả về giá trị không nhất quán cho hàm tạo riêng


13

Các quy tắc mà std::is_constructiblexử lý các nhà xây dựng tư nhân là gì? Cho mã sau:

#include <iostream>

class Class {
private:
    Class() { }
};

template <typename T>
class Test {
public:
    static void test() {
        std::cout
            //<< std::is_constructible<Class>::value
            << std::is_constructible<T>::value
            << std::endl;
    }
};

int main() {
    Test<Class>::test();
}

Bản in này 0( ideone ), nghĩa là, Tkhông thể xây dựng mặc định.

Không chú ý đến dòng nhận xét, nó in 11( ideone ), do đó, hoàn toàn Ttrở thành cấu trúc mặc định.

Tôi có thể tìm thấy lý do để hỗ trợ cả hai kết quả, nhưng tôi không hiểu cách bao gồm dòng nhận xét thay đổi kết quả của lần thứ hai. Đây có phải là bằng cách nào đó gọi UB? Đây có phải là một lỗi biên dịch? Hay là std::is_constructiblethực sự không nhất quán?


1
Trông giống như một lỗi GCC, in 9 bản in00
Yksisarvinen

1
Một suy nghĩ kỳ lạ khác mà tôi nhận thấy khi biên dịch tại máy của mình với c ++ 17 g ++ 9.2.1 / g ++ - 10.0 và thay thế std :: is_constructible <...> :: value bằng is_constructible_v <...>, đó có phải là kết quả thay đổi thành 00
mutableVoid

1
@mutableVoid Thật vậy - và dường như ::valuephiên bản có khả năng thay đổi đầu ra của những người đến trước nó: godbolt.org/z/zCy5xU Bỏ ghi chú dòng nhận xét và tất cả trở thành 1: s trong gcc.
Ted Lyngmo

1
Một cách khác để khắc phục: godbolt.org/z/EKaP3r vì vậy về cơ bản đây là một số lỗi đánh giá thứ tự.
Marek R

2
@mutableVoid Bạn thậm chí không cần phải khởi tạo mẫu hàm để nó trở thành đúng. Trong ví dụ này, nó trả về falsenhưng nếu mẫu hàm không bị lỗi, nó đột nhiên trả về true: godbolt.org/z/zqxdk2
Ted Lyngmo

Câu trả lời:


3

std::is_constructiblenên trả về falsetrong kịch bản này bởi vì hàm tạo không thể truy cập được.

Như được chỉ ra bên dưới câu hỏi, hành vi được mô tả trong câu hỏi là do lỗi trong GCC / libstdc ++. Lỗi được báo cáo ở đây và, theo Bugzilla, liên quan đến việc nếu không phải do lỗi kiểm soát truy cập gây ra cho các lớp trong các hàm mẫu đã không được giải quyết trong một thời gian dài. Mối quan hệ giữa hai lỗi được lấy từ bình luận Bugzilla của Jonathan Wakely, người dường như đã phát hiện ra mối liên hệ giữa hai lỗi trước tiên.

Điều này cũng được ngụ ý bởi thực tế là hành vi của kịch bản này trong GCC trở nên chính xác khi xóa hàm tạo thay vì đặt ở chế độ riêng tư:

class Class {
    Class() = delete;
};

mà in ra 000tương ứng. Đây là đầu ra chính xác ( clangbáo cáo chính xác trong kịch bản với hàm tạo riêng tư).

Điều này có thể giải thích sự thay đổi hành vi được quan sát khi nhận xét trong dòng, bởi vì bên trong hàm trong cấu trúc templated , kiểm tra truy cập không hoạt động và báo cáo rằng hàm tạo có thể truy cập được khi không. Khi tính trạng được kiểm tra lại ở dòng tiếp theo hoặc có thể ở một vị trí hoàn toàn khác (như trường hợp ở đây ), nó đã được khởi tạo và do đó đưa ra câu trả lời sai.

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.