2011-10-14 31 views
7

Sau đây thất bại trong việc biên dịch trên VC++ 8.0 biên dịch với một lỗi (Tôi đã không thử nó trên trình biên dịch visual studio mới nhất được nêu ra.)Trích đối số mẫu không thành công trên MSVC: lỗi?

lỗi C2440: 'return': không thể chuyển đổi từ 'const char *' thành ' const char (&) [6]'

template <typename T> 
inline T const& compare (T const& a, T const& b) 
{ 
    return a < b ? b : a; 
} 

int main() 
{ 
    ::compare("string1", "string2"); 
} 

Bên trong hàm mẫu, có vẻ như chuỗi là const char (&)[6].

Theo như tôi biết, khi áp dụng toán tử <, mảng sẽ bị phân rã thành con trỏ. Vì vậy, lỗi này có thể do lỗi có thể xảy ra không?

+0

gcc [biên dịch] (http://ideone.com/WVU4h) mã này mà không gặp bất kỳ sự cố nào, vì vậy đây phải là lỗi trong MSVC. – Vlad

+1

Dường như bạn không muốn chuyển chuỗi C vào mẫu như vậy (để so sánh địa chỉ của chúng). – UncleBens

+0

Điều này trông giống như một lỗi, MSVC nói loại biểu thức 'a Praetorian

Trả lời

3

Đây chắc chắn là lỗi trong trình biên dịch của Microsoft.

Dưới đây là một sự khác biệt lớn trong C và C++.

e0 ? e1 : e2 

Trong C++, một condtional thể hiện sản xuất vế trái, trừ ít nhất một trong các biểu thức trong phần thứ hai (sau '?') là một rvalue, trong khi ở C, một conditional- biểu thức luôn tạo ra rvalue, bất kể là gì. Điều đó có nghĩa, các mã sau đây là hoàn toàn hợp lệ trong C++ nhưng nó là một lỗi trong C:

int a=10, b=20; 
(a<b?a:b) = 100; //ok in C++, but error in C 

Trong C++, nó sẽ không đưa ra bất cứ lỗi, chính vì sự biểu hiện (a<b?a:b) là biểu hiện giá trị trái, như vậy là bạn có thể đặt nó ở phía bên trái của một bài tập.

Bây giờ, quay lại câu hỏi gốc. Trong trường hợp của bạn, ab là các loại của char (&) [6] và biểu thức a<b? a : b sẽ tạo ra một giá trị, vì không cần chuyển đổi mảng thành con trỏ. Nhưng trong trình biên dịch của Microsoft, có vẻ như có chuyển đổi mảng thành con trỏ.

Để xác minh điều đó, người ta có thể viết này:

template <typename T, int N> 
inline void f(T const (&a)[N]) {} 

template <typename T> 
inline T const& compare (T const& a, T const& b) 
{ 
    f(a < b ? b : a); //is the argument `char*` OR `char (&)[6]`? 
    return a < b ? b : a; 
} 

Và nó mang lại cho no error một trong hai (trong GCC), có nghĩa là sự biểu hiện mà bạn vượt qua để f() là một mảng, không phải là một con trỏ.

+0

Mặc dù chính xác cho tình huống này, câu lệnh của bạn về việc liệu một biểu thức có điều kiện là _lvalue_ là quá mạnh. Cả hai biểu thức thứ hai và thứ ba có thể là _glvalues_, nhưng biểu thức vẫn có thể là _prvalue_ nếu chúng không có cùng loại và việc chuyển đổi một trong hai loại đó thành một loại phổ biến không mang lại _glvalue_ ràng buộc trực tiếp. –

+0

@CharlesBailey: Tôi nghĩ những gì bạn nói là đúng cho C++ 11, và C++ 03 không có những khái niệm đó. Bài viết của tôi là về C++ 03, như OP đang sử dụng MSVS 2008 mà không thực hiện các tính năng C++ 11. – Nawaz

+0

Rõ ràng, bạn phải đọc _lvalue_ cho _glvalue_ và _rvalue_ cho _prvalue_, nhưng về cơ bản điều này vẫn đúng trong C++ 03. –

0

Theo như tôi biết, khi áp dụng toán tử <, mảng sẽ bị phân rã thành con trỏ.

Đó là vấn đề, nó đang được phân rã thành const char * nhưng sau đó nó đang cố gắng chuyển đổi thành const char [8] cho giá trị trả về.

Tôi không chắc chắn những gì tiêu chuẩn nói về vấn đề này, nhưng nếu bạn thay đổi nó hoặc là:

compare<char *>("string1","string2"); 

hoặc

compare(static_cast<const char *>("string1"),static_const<const char *>("string2")); 

Sau đó các mẫu tham số T sẽ char * thay char [8].

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