2013-04-26 50 views
3

這是一個my previous post複述,因爲我改變了這個問題(所以它可能沒有被標記爲一個新的問題,並錯過了)。我希望可以減少它。數組如何與條件運算符一起工作?

我有功能,如:

#include <cstddef> 
#include <type_traits> 

template < typename E, typename T > 
inline constexpr 
auto checked_slice(E &&, T &&t) noexcept -> T && 
{ return static_cast<T &&>(t); } 

template < typename E, typename T, std::size_t N, typename U, typename ...V > 
inline constexpr 
auto checked_slice(E &&e, T (&t)[N], U &&u, V &&...v) 
-> typename remove_some_extents<T, sizeof...(V)>::type & 
{ 
    typedef typename std::remove_reference<U>::type     u_type; 
    typedef typename std::common_type<u_type, std::size_t>::type cmp_type; 

    return (u < u_type{}) || (static_cast<cmp_type>(u) >= 
    static_cast<cmp_type>(N)) ? throw e : checked_slice(static_cast<E &&>(e), 
    t[static_cast<U &&>(u)], static_cast<V &&>(v)...); 
} 

其中remove_some_extents是一個自定義類模板就像調用std::remove_extent元函數的給定的次數。

當我試圖運行程序,我有一堆像錯誤:「從Whatever(*)[Y]類型的表達Whatever(&)[X][Y]類型的參考無效初始化」(或Whatever(&)[Z]Whatever*)。我的解決方法是將條件表達式轉換爲if - else對(並刪除constexpr)。

我想弄清楚什麼是錯的,所以我在C++(2011)標準中討論有關條件運算符的部分。這是第5.16節。當兩個可能的操作之一是throw命令(或者是其他的void表達式)時,那麼該條件具有另一個表達式的類型,但是標準轉換(包括數組到指針)應用於該另一個表達式。 (這是在第2段。)我認爲這就是搞砸了我。有沒有辦法解決它?我認爲返回數組引用會抑制a-to-p轉換。爲什麼它在製作成if/else時工作?

回答

4

你的分析是正確的。我懷疑在這種情況下,非void操作數是「衰減的」(也就是執行通常的轉換),以便模擬兩種操作數在類型上有所不同時發生的情況 - 後者通常不是整個條件表達式是一個前值。

中,我們知道肯定值類別和條件表達式是當兩個操作數完全匹配,因此我們可以使用的類型兩者的一種情況是我們的優勢:

cond ? (throw e, t) : t 

將是一個左值數組引用類型。 (當然,最後的操作並不一定是字面上t - 你可以將你的遞歸調用在這裏就好了。)

使用if/else時,您沒有遇到任何障礙等,因爲作爲語言做了發言不必爲它指定一個通用的類型和值類別。

+0

從在編譯器網頁上進行測試,您不需要括號! '?:'的語法是'LOGICAL_OR_EXPR? EXPR:ASSIGN_EXPR'。第三部分可以是除逗號操作符之外的任何內容。第二節不*有這種限制! (第一部分是比'?:'更高優先級的任何東西。) – CTMacUser 2013-04-27 10:56:27

+0

括號對於編譯器來說很少有用。 – 2013-04-27 11:08:39

+0

答案奏效。你可以看到[代碼](https://github.com/CTMacUser/ArrayMD/blob/master/include/boost/utility/slice.hpp),提交SHA 66ca088332dd1e57fdaf9e90749105224c301afb,行136到159。 – CTMacUser 2013-04-27 12:27:54

相關問題