2013-03-13 20 views
11

Tôi đang cố gắng cập nhật dự án cũ đã được xây dựng với studio trực quan 2005 để sử dụng studio hình ảnh 2012 và tôi nhận được một lỗi mà tôi không thể giải quyết.C++ loại bỏ mã toán tử sẽ không biên dịch trong studio hình ảnh 2012, nhưng đã làm việc tốt trong studio trực quan 2005

Các mã mà hoạt động tốt dưới VS2005:

#include <iostream> 
#include <string> 
#include <sstream> 

using std::cout; 
using std::wcout; 
using std::endl; 
using std::wstring; 
using std::string; 


class Value 
{ 
public: 
    Value(const wstring& value) 
    { 
     v = value; 
    } 

    Value(Value& other) 
    { 
     this->v = other.v; 
    } 

    template<typename T> 
    operator T() const 
    { 
     T reply; 
     std::wistringstream is; 
     is.str(v); 
     is >> reply; 
     return reply; 
    } 

    operator wstring() const 
    { 
     return v; 
    } 


private: 
    wstring v; 
}; 


int main() 
{ 
    Value v(L"Hello World"); 

    wstring str = v; 
    wcout << str << endl; 

    Value int_val(L"1"); 
    int i = int_val; 

    cout << i + 1 << endl; 

    return 0; 
} 

Khi tôi biên soạn này dưới VS2012 tôi nhận được một lỗi trên dòng "wstring str = v;", lỗi này là:

error C2440: 'initializing' : cannot convert from 'Value' to 'std::basic_string<_Elem,_Traits,_Alloc>' 
1>   with 
1>   [ 
1>    _Elem=wchar_t, 
1>    _Traits=std::char_traits<wchar_t>, 
1>    _Alloc=std::allocator<wchar_t> 
1>   ] 
1>   No constructor could take the source type, or constructor overload resolution was ambiguous 

Tôi có thể sửa lỗi bằng cách thay đổi chữ ký toán tử từ 'toán tử wstring() const' thành 'toán tử const wstring &() const'. Nhưng tại sao mã gốc không hoạt động, mặc dù nó hoạt động trong VS2005.

Tôi không gặp lỗi trên dòng "int i = int_val;".

Điều này cũng biên dịch và chạy tốt với GCC (g ++) trong Cygwin (phiên bản 4.5.3).

Cập nhật Để thực sự mô phỏng vấn đề thực sự của tôi, có một số thông tin còn lại trong mã mẫu ở trên. Ở giữa lớp Value và cách sử dụng là một vài lớp khác. Một hình như sau:

class Config 
{ 
public: 
    virtual Value getValue(const string& key) const = 0; 

    Value operator()(const string& key) 
    { 
     return getValue(key); 
    } 
}; 

Và cách sử dụng const wstring value2 = config ("key");

Điều đó sẽ cung cấp lỗi ở trên khi biên dịch nhưng IntelliSense sẽ cung cấp các gợi ý khác về sai và nói: "Nhiều chuyển đổi do người dùng xác định từ" Giá trị "thành" const std :: wstring "áp dụng:" và nó trỏ vào cả hàm tạo thông thường và hàm khởi tạo của basic_string. Vì vậy, nó dường như có một cái gì đó để làm với rvalues ​​để làm và tôi đã được đọc lên trên đó, và hiểu những điều cơ bản. Nhưng có lẽ rất nhiều tôi đang mất tích.

Tôi thấy rằng tôi có thể khắc phục sự cố này bằng cách thay đổi cách sử dụng thành: const wstring & & giá trị = config ("khóa");

Sau đó, nó có vẻ như trình biên dịch VS2012 hiểu được constructor nó nên sử dụng sau đó.

Câu hỏi: * Có cách nào để không sử dụng & & trong ví dụ này không? * Điều gì thực sự xảy ra ở đây?

tôi đặt lên đoạn code mẫu trên GitHub: https://github.com/Discordia/ImplicitTypeConversion

+3

Biên dịch tốt với Clang Trunk, vì vậy tôi đoán đó là lỗi với độ phân giải quá tải của chúng, không chọn mẫu không phải trước mẫu (trên các UCS khác nhau có thể). Lưu ý rằng có hai hàm tạo khả thi: Một hàm nhận 'wstring &&' và cũng là một hàm nhận 'wchar_t const *'. Cái trước sẽ gọi op chuyển đổi 'wstring', trong khi cái sau sẽ gọi ra khuôn mẫu chuyển đổi op. – Xeo

+0

@Xeo: Hoặc một lỗi phổ biến trong nhiều trình biên dịch. Trên một cái nhìn lướt qua nhanh chóng trong tiêu chuẩn nó * có vẻ * rằng VS có thể ở ngay tại đây. Tôi không tìm thấy bất kỳ quy tắc nào xác định rằng phiên bản không phải mẫu được ưu tiên so với phiên bản mẫu và không có quyền ưu tiên toán tử chuyển đổi không rõ ràng khi chuyển đổi thành 'std :: wstring' và tiêu chuẩn yêu cầu mã không thành công. –

+0

@David: '§13.3.3/1:' "Với các định nghĩa này, một hàm khả thi' F1' được định nghĩa là một hàm tốt hơn hàm khả thi khác 'F2' nếu [...]' F1' là một chức năng không phải mẫu và 'F2' là một chuyên môn về mẫu chức năng [...]" – Xeo

Trả lời

1

Trong đơn giản (hy vọng không đơn giản) điều khoản, với C++ 11, bạn sẽ phải bắt đầu suy nghĩ về tài liệu tham khảo về giá trị trái và rvalue. Về cơ bản, C++ 11 cung cấp cho bạn khả năng xử lý các thao tác trên các tham chiếu khác nhau tùy thuộc vào việc bạn có đang xử lý đối tượng "tạm thời" hay không. Điều này cho phép bạn làm những việc như di chuyển dữ liệu bên trong đối tượng của bạn thay vì sao chép trong các tình huống khác nhau. Phía bên dưới là hiệu ứng bạn đang thấy, ở đó mã cũ không đủ cụ thể về việc bạn đang xử lý. Có nhiều điều hơn thế nữa, nó không thực sự là một cái gì đó có thể được giải thích đầy đủ trong một câu trả lời SO ngắn, nhưng trước đó answers đã cho một số good places để bắt đầu. Tôi sẽ làm lại mã của bạn để cung cấp cả hai nhà khai thác giá trị và giá trị (có vẻ như bạn đã sẵn sàng để làm).

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