2011-10-14 94 views
7

下未能在VC++ 8.0編譯器編譯錯誤(我還沒有嘗試過的最新的Visual Studio編譯呢。)MSVC模板參數推導失敗:錯誤?

錯誤C2440:「迴歸」:不能轉換從「常量字符*」到 '常量 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"); 
} 

裏面的函數模板,似乎字符串const char (&)[6]

據我所知,當應用<運算符時,數組應該被衰減爲指針。 那麼,這個錯誤可能是因爲可能的錯誤?

+0

gcc [編譯](http://ideone.com/WVU4h)此代碼沒有任何問題,所以這必須是MSVC中的一個錯誤。 – Vlad

+1

無論如何,你不想將C字符串傳遞給這樣的模板(比較它們的地址)。 – UncleBens

+0

這確實看起來像一個錯誤,MSVC說表達式的類型'a Praetorian

回答

3

這確實是Microsoft編譯器中的一個錯誤。

這是C和C++中的一個重大差異。

e0 ? e1 : e2 

在C++中,一個condtional表達產生左值除非在第二部分中的表達的至少一種('?'之後)是右值,而在C,一個conditional-表達式總是產生右值,無論如何。這意味着,下面的代碼在C完全有效++,但它是C的一個錯誤:

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

在C++中,它不會給任何錯誤,正是因爲表達(a<b?a:b)是左值表達式,所以你可以把它在任務的左側。

現在回到原來的問題。在你的情況下,ab是類型爲char (&) [6]的數組,並且表達式a<b? a : b應該產生左值,因爲不需要數組到指針的轉換。但在微軟的編譯器中,似乎有陣列對指針的轉換。

要驗證它,可以寫:

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; 
} 

和它給no error或者(在GCC),這意味着它傳遞給f()是一個數組,不是指針的表達。

+0

儘管對於這種情況正確,但是關於條件表達式是否爲_lvalue_的陳述太強烈了。第二個和第三個表達式都可以是_glvalues_,但是如果表達式可能仍然是_prvalue_,如果它們不具有相同的類型,並且它們中的任何一個的轉換都不會產生直接綁定的_glvalue_。 –

+0

@CharlesBailey:我認爲你所說的僅適用於C++ 11,而C++ 03不具備這些概念。我的帖子是關於C++ 03的,因爲OP使用的是MSVS 2008,它沒有實現C++ 11功能。 – Nawaz

+0

很明顯,你必須爲_prvalue_讀取_lvalue_作爲_glvalue_和_rvalue_,但從根本上說,這在C++ 03中仍然是正確的。 –

0

就我所知,當應用<運算符時,數組應該被衰減爲指針。

這就是問題所在,它正在腐朽爲const char *但當時它正試圖將其轉換成const char [8]返回值。

我不知道是什麼標準說這個,但如果你將它更改爲:

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

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

然後模板參數Tchar *代替char [8]