2014-08-28 16 views
5

Tôi có đoạn code sau đây với một lớp tùy chỉnh Ngôn ngữ địa phương và một tùy chỉnh SmartPtr lớp:tự động chuyển đổi bool để nullptr_t

using namespace std; 

class Object 
{ 
public: 
}; 

template<typename T> 
class SmartPtr 
{ 
public: 

    template<typename Y> 
    explicit SmartPtr(Y* p) { p_ = p; } 

    SmartPtr(std::nullptr_t) { p_ = nullptr; } 

private: 
    T* p_; 
}; 

class Variant 
{ 
public: 
    Variant(bool b) : _b(b) { } 

private: 
    bool _b; 
}; 

class Obj 
{ 
public: 
    void test(SmartPtr<Object> /*p*/) { cout << "smartptr version!" << endl; } 
    void test(Variant /*v*/) { cout << "variant version!" << endl; } 
}; 

int main(int argc, const char *argv[]) 
{ 
    Obj o; 
    o.test(nullptr); // calls SmartPtr version 
    o.test(true); // calls Variant version 
    o.test(false); // -> compiler error: ambiguous call to overloaded function 

    return 0; 
} 

Tôi giả định rằng sai boolean có thể được chuyển đổi cả các biến thể và 0 sau đó đến nullptr và sau đó để SmartPtr, gây ra lỗi này.

Bất kỳ cơ hội nào để tránh chuyển đổi này?

Dành cho người dùng thư viện API hoạt động với 'o.test (true);' nhưng yêu cầu một cái gì đó như 'o.test (Biến thể (sai));' để biên dịch không phải là rất trực quan.

+0

Trình biên dịch khác nhau xử lý mã này khác nhau. g ++ (C++ 1y) thất bại ở cả 'nullptr' và' false'. clang (C++ 1y) không thành công tại 'nullptr'. Câu hỏi liên quan: http://stackoverflow.com/questions/17501942/false-implicitly-convert-to-null-pointer/ – zch

+0

Tôi nghĩ rằng trình biên dịch tuân thủ chuẩn nên chấp nhận toàn bộ mã ('nullptr_t -> SmartPtr' tốt hơn' nullptr_t -> bool -> Biến thể' và 'bool -> nullptr_t -> SmartPtr' không hợp lệ), nhưng tôi đoán nó không giúp ích nhiều cho bạn. Tôi khuyên bạn nên sử dụng tên hàm riêng biệt. – zch

+0

@zsh: Tôi đang sử dụng cả clang và g ++ với std = C++ 11 trên linux cũng như vc12 trên windows, thông báo lỗi giống nhau. Thật không may, một cách đặt tên khác nhau đã hết câu hỏi vì mã đã hoạt động trước đó và tôi cố gắng giới thiệu hàm tạo nullptr_t cho lớp SmartPtr khiến cho việc biên dịch thất bại. – mgr

Trả lời

1

Tôi tin rằng tôi có một giải pháp lý tưởng. Nó chỉ yêu cầu chức năng kiểm tra bị thay đổi, vì vậy nó chỉ để lại SmartPtr và Biến thể một cách lý tưởng. Nó bổ sung thêm một quá tải không định nghĩa templated để kiểm tra có các chuyên môn cho bool và nullptr được định nghĩa. Điều này trực tiếp gửi bool và nullptr đến chuyên môn mong muốn, nhưng gây ra lỗi liên kết trên các loại không được xử lý khác. Tôi rất vui vì điều này đã được giải quyết bởi vì tôi chắc chắn đã tự mình điều hành nó dưới nhiều hình thức. Tôi muốn bạn có thể sử dụng các thông số chức năng rõ ràng !!

tôi đã có ý tưởng từ đây: C++ templates that accept only certain types

using namespace std; 

class Object 
{ 
public: 
}; 

class Variant 
{ 
public: 
    Variant(bool b) : _b(b) { } 

private: 
    bool _b; 
}; 

template<typename T> 
class SmartPtr 
{ 
public: 
    SmartPtr(std::nullptr_t null) { p_ = nullptr; } 

    template<typename Y> 
    SmartPtr(Y* p) { p_ = p; } 

private: 
    T* p_; 
}; 

class Obj 
{ 
public: 
    void test(SmartPtr<Object> here /*p*/) { 
     cout << "smartptr version!" << endl; 
    } 
    void test(Variant /*v*/) { cout << "variant version!" << endl; } 

    template<typename T> void test(T t); 

    template<> 
    void test<bool>(bool b) { 
     cout << "bool specialization" << endl; 
     test(Variant(b)); 
    } 

    template<> 
    void test<std::nullptr_t>(std::nullptr_t null) { 
     cout << "nullptr specialization" << endl; 
     test(SmartPtr<Object>(nullptr)); 
    } 
}; 

int main(int argc, const char *argv[]) 
{ 
    Obj o; 
    Obj c; 
    Object object; 

    //o.test(3); // Gives link error LNK2019 

    o.test(Variant(true)); // calls Variant version 
    o.test(SmartPtr<Object>(&object)); // calls SmartPtr version 
    o.test(nullptr); // dispatched to SmartPtr version by nullptr specialization 
    o.test(true); // dispatched to Variant version by bool specialization 
    o.test(false); // dispatched to Variant version by bool specialization 
    return 0; 
} 

tôi đã trả lời với một cái gì đó không lý tưởng, vì vậy tôi rời khỏi rằng câu trả lời một cách tinh tế như những gì sau:

======= ======================================

Tôi không có giải pháp lý tưởng ở đây, và tôi không biết những ràng buộc bạn có trên mã của bạn vì vậy điều này có thể không được sử dụng chức năng cho bạn, nhưng sau đây là hợp lý. Nó không cho phép mã sử dụng nullptr tại thời gian biên dịch và dựa vào hằng số null_smart toàn cục được sử dụng trong tất cả các trường hợp mà người gọi chỉ đơn giản là không quan tâm đến việc truyền một đối tượng.

#include <iostream> 

using namespace std; 

class Object 
{ 
public: 
}; 

class Variant 
{ 
public: 
    Variant(bool b) : _b(b) { } 
private: 
    Variant(std::nullptr_t) {}; 

private: 
    bool _b; 
}; 

template<typename T> 
class SmartPtr 
{ 
public: 
    SmartPtr() { p_ = nullptr; } 

    template<typename Y> 
    SmartPtr(Y* p) { p_ = p; } 

private: 
    T* p_; 
}; 

class Obj 
{ 
public: 
    void test(SmartPtr<Object> /*p*/) { cout << "smartptr version!" << endl; } 
    void test(Variant /*v*/) { cout << "variant version!" << endl; } 
}; 

const SmartPtr<Object> null_smart; 

int main(int argc, const char *argv[]) 
{ 
    Obj o; 
    o.test(null_smart); // calls SmartPtr version, without interest in passing object 
    o.test(true); // calls Variant version 
    o.test(false); // calls Variant version 
    return 0; 
} 

Nó sạch hơn sự thật/Biến thể (sai) vấn đề, nhưng vẫn hơi ở phía cầu kỳ.

+0

Đối tượng với phương thức test() nằm trong mã người dùng, đã tồn tại trước ý tưởng của tôi để có một cú pháp con trỏ null đồng nhất cho tất cả các lớp SmartPtr thô và tùy chỉnh. – mgr

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