2016-03-07 21 views
8

Phương pháp trong C++ 14 có thể nói cho dù họ đang kêu gọi một L-giá trị hoặc một R có giá trị:Ngăn chặn instantiation L-giá trị trong C++ 14

struct A{ 
    A() { puts("Ctor"); } 
    void m() const & { puts("L-value"); } 
    void m() const && { puts("R-value"); } 
}; 

int main(){ 
    A a; //Ctor 
    a.m() //L-value 
    A().m(); //Ctor; R-value 
} 

một ctor thể cho loại nó đang xây dựng? Tôi có thể tắt hoàn toàn việc xây dựng các giá trị L từ lớp học của mình không?

Tôi có một lớp proxy (một số, trên thực tế), nên luôn chuyển đổi thành một thứ khác. Sử dụng nó mà không cần chuyển đổi là một lỗi. Tôi có thể phát hiện lỗi đó trong thời gian chạy, ví dụ: bằng cách thêm bool used_ = 0; thành viên #ifndef NDEBUG; và đặt nó trong diễn viên do người dùng chỉ định và sau đó thực hiện assert(used_) trong lớp proxy Dtor, tuy nhiên sẽ đẹp hơn nếu tôi có thể truy cập trình biên dịch để ngăn chặn instatiation của L-value trường hợp của proxy đó ở nơi đầu tiên:

auto x = Proxy().method1().method2(); // no 
Proxy p; // no 
Target x = Proxy(); //yes 
Target x = Proxy().method1().method2(); //yes 

Tôi có thể làm điều gì đó tương tự với C++ 14 không?

+6

Cách học cũ để đạt được điều bạn muốn là đặt hàm tạo thành riêng tư và chỉ cho phép xây dựng thông qua các phương thức tĩnh. Tôi nghĩ điều đó cũng trực quan hơn với người làm việc với mã của bạn. – ypnos

+1

'auto && x = Proxy();' không thể ngăn chặn IIRC. Và sau đó 'x' là một Proxy lvalue có thể sửa đổi được. – dyp

+0

Tôi có cảm giác câu trả lời vẫn không có và bạn phải làm những gì ypnos gợi ý – NathanOliver

Trả lời

2

Tại sao, tất nhiên:

#include <iostream> 
using namespace std; 

class B; 

class A 
{ 
public: 
    A(B&& b) {} 

    A(const B&) = delete; 
}; 

class B {}; 

int main() 
{ 
    B b; 

    // A a1; <- error 
    // A a2 = b; // <- error 
    A a3 = move(b); // <- fine 

    return 0; 
} 
+0

Theo như tôi hiểu 'A a3 = move (b);' không được phép biên dịch vì 'a3' là một giá trị. – nwp

+0

Trong trường hợp đó, đoạn mã không giúp gì cả, ngay – IceFire

+0

Cảm ơn. Sẽ sử dụng cái này. Đủ gần rồi. – PSkocik

3
struct temporary_only { 
    static temporary_only make() { return {}; } 
    temporary_only(temporary_only&&)=delete; 
    int get()&& { return 3; } 
private: 
    temporary_only() {} 
}; 

int main() { 
    //temporary_only x; // illegal 
    std::cout << temporary_only::make().get() << '\n'; // legal 
} 

live example.

Chúng tôi vô hiệu hóa tất cả các ctors công cộng (bao gồm sao chép/di chuyển), vì vậy không ai có thể tạo ra một temporary_only ngoại trừ thông qua temporary_only::make (một giá trị).

Lưu ý rằng

temporary_only&& a = temporary_only::make(); 

vẫn hoạt động. Ở đây chúng tôi có một rvalue ràng buộc với một tham chiếu rvalue, và tham chiếu rvalue chính nó là một giá trị với một đời sống đa dòng (tuổi thọ phạm vi). Điều này không thể dừng lại được.

+0

Ngoài ra 'const temporary_only & a = temporary_only :: make();' hoạt động tốt – NathanOliver

+0

Và để làm cho vấn đề tồi tệ hơn 'std :: move (a) .get()' cũng hoạt động tốt. – nwp

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