2014-09-04 32 views
7

Nhìn vào mã:Tại sao tôi có thể sử dụng hàm tạo mặc định riêng tư trong decltype()?

#include <iostream> 
#include <utility> 

class test 
{ 
private: 
    test() { } 
public: 
    test foo() { return *this; } 

    static const char *name() { return "test"; } 
}; 

int main() 
{ 
    std::cout << decltype(test().foo())::name() << std::endl;    // 1 
    std::cout << decltype(std::declval<test>().foo())::name() << std::endl; // 2 
} 

tôi mong đợi // 1 dòng không thể được biên dịch bởi vì các nhà xây dựng mặc định của test là tư nhân.

However, it works well. Tôi đã thử nghiệm trên g ++ 4.8.3 của tôi với -Wall -Wextra -Werror -pedantic với sự hoài nghi, nhưng nó hoạt động tốt mà không có bất kỳ lỗi hoặc cảnh báo nào.

(Bên cạnh đó, có vẻ như để làm việc tốt trong GCC 4.9.1 là tốt.)

Từ this page, tôi đoán chúng ta có thể sử dụng constructor mặc định riêng nếu biểu thức là unevaluated. Vì vậy, tôi đã kiểm tra những điều sau đây để kiểm tra nó.

#include <iostream> 
#include <utility> 

class test 
{ 
private: 
    test(int) { } 
public: 
    test foo() { return *this; } 

    static const char *name() { return "test"; } 
}; 

int main() 
{ 
    std::cout << decltype(test().foo())::name() << std::endl;    // 1 
    std::cout << decltype(std::declval<test>().foo())::name() << std::endl; // 2 
} 

(live example)

Đúng như dự đoán, nó không được biên dịch.

Nhưng .... tại sao ?? Làm cách nào để có thể? Chúng tôi có thể sử dụng riêng tư thành viên trong biểu thức chưa được đánh giá không? Hoặc là có một quy tắc đặc biệt cho các nhà thầu mặc định? Bạn có thể giải thích cho tôi tại sao?

+0

Không biên dịch trong tiếng kêu. –

+0

@ T.C. Oh thật sao? sau đó nó có thể chỉ là lỗi của GCC .. – ikh

+1

Um, C++ 98 không có 'decltype'. Hoặc 'declval'. Tất nhiên nó không biên dịch. –

Trả lời

11

Nó không nên biên dịch. C++ 11 [class.temporary] có này để nói về việc tạo ra một đối tượng tạm thời:

12,2/1 Ngay cả khi việc tạo ra các đối tượng tạm thời là unevaluated hoặc tránh được, tất cả các hạn chế ngữ nghĩa sẽ được tôn trọng như thể vật thể tạm thời đã được tạo ra và sau đó bị phá hủy. [Lưu ý: ngay cả khi không có lệnh gọi hàm hủy hoặc trình tạo bản sao/di chuyển, tất cả các hạn chế ngữ nghĩa ngữ nghĩa, chẳng hạn như khả năng truy cập và liệu chức năng có bị xóa hay không. Tuy nhiên, trong trường hợp đặc biệt của một cuộc gọi chức năng được sử dụng làm toán hạng của decltype-specifier, không có tạm thời được giới thiệu, do đó, ở trên không áp dụng cho giá trị của bất kỳ cuộc gọi chức năng như vậy. - cuối note]

Vì vậy, ngay cả khi unevaluated, bạn vẫn bị hạn chế bởi khả năng tiếp cận của bất kỳ chức năng (bao gồm cả nhà xây dựng) cần thiết để tạo ra và phá hủy tạm thời. Câu cuối cùng của ghi chú làm rõ rằng một hàm như declval có thể được sử dụng để tránh chướng ngại vật này.

+1

Cảm ơn . +1 cho * câu cuối cùng *. (Ồ, tôi thấy tôi không thể chấp nhận câu trả lời trong một phút> o <) – ikh

+0

Sau đó, nó phải là lỗi của gcc; tôi có nên báo cáo không? > o < – ikh

Các vấn đề liên quan