2013-02-19 82 views
3

Expression SFINAE是一種非常方便的方式來編寫幾個替代功能來做同樣的事情,並選擇最好的編譯。你在函數原型中提到了關鍵表達式,如果它們是無效的,原型將被忽略,並且希望能夠挑選出另一個。表達式中的習慣性表達sfinae

這是非常方便的,除了在表達式未定義的情況下聲明原型。通常這組原型必須分成互斥域,因爲它們在重載分辨率方面可能是相等的,並且允許兩個進入重載集會造成模糊性。

人們總是可以定義爲一個給定的表達std::enable_if老式的特質類型,用途:

template< typename s, typename t, typename u, typename = void > 
struct is_product_serializable : std::false_type {}; 

template< typename s, typename t, typename u > 
struct is_product_serializable< s, t, u, typename std::conditional< true, void, 
    decltype(std::declval<s>() << std::declval<t>() * std::declval<u>()) 
>::type > 
    : std::true_type {}; 

如果不是因爲需要的東西從false_type派生的std::conditional可以去直接進入函數原型,所有這些樣板都會消失。

有沒有其他的選擇?也許有一種方法可以減少不影響類型扣除的函數重載的排名?

+0

我還沒有完全明白這個問題。你爲什麼不能把這些條件放在函數原型上?你說「如果不是需要從'false_type'派生':爲什麼需要?如果你想使用標籤調度,那就只是這種情況,但你並不是被迫的。爲什麼你不能在函數原型中使用類型名稱enable_if > :: type'?也許我還沒有理解你的想法。 – 2013-02-20 02:38:48

+0

@AndyProwl你命名了一個條件。那麼相反的情況呢? – Potatoswatter 2013-02-20 03:33:19

回答

0

一種替代方法是添加一個調度器函數,它爲擺動空間添加一個虛擬參數(如標籤),以使參數列表不同。

// "Primary" template is just a dispatcher 
template< typename ... args > 
void chuck(args && ... rem) { 
    return chuck_impl(0, std::forward<args>(a) ...); 
} 

// preferred alternative matches int to 0 but is controlled by SFINAE 
template< typename t, typename u, typename ... args > 
auto chuck_impl(int, t && a, u && b, args && ... rem) 
-> typename std::conditional< true, void, decltype(blah(a, rem ...) * b) >::type { 
    blah(a, rem ...) * b; 
} 

// fallback requires int => float conversion 
template< typename t, typename u, typename ... args > 
void chuck_impl(float, t && a, u && b, args && ... rem) { 
    bleh(a + chuck_impl(b, rem ...)); 
} 
+0

你可能會把SFINAE清理成' - > decltype((blah(a,rem ...)* b),void())'。 – Xeo 2013-02-20 08:04:22

+0

@Xeo GCC中唯一可靠的工作是'std :: conditional'。我厭惡嘗試替代品。更清潔的版本將會是'decltype(void(blah(a,rem ...)* b)))''。 – Potatoswatter 2013-02-20 09:31:28

+0

對於一個版本的工作是沒有意義的,對於另一個版本是不合理的,它們都使用相同的機制,即如果'decltype'內的表達式格式不正確,則會得到一個軟錯誤。 – Xeo 2013-02-20 09:33:51