2017-03-10 14 views
0

我一直在試圖通過閱讀下面的文章Link瞭解SFINAE的招數,但在理解它的某些部分有困難。需要澄清lambda表達式,汽車和decltype在SFINAE

全碼:Link

我感到困惑主要是關於這些代碼行。

// Check if a type has a serialize method. 
auto hasSerialize = is_valid([](auto&& x) 
    -> decltype(x.serialize()) { }); 

template <class T> auto serialize(T& obj) 
    -> typename std::enable_if<decltype(hasSerialize(obj))::value, std::string>::type 
{ 
    return obj.serialize(); 
} 

template <class T> auto serialize(T& obj) 
    -> typename std::enable_if<!decltype(hasSerialize(obj))::value, std::string>::type 
{ 
    return to_string(obj); 
} 

尤其是使用hasSerialize行,它在帶參數的decltype中使用。誰能告訴我這裏有什麼? hasSerialize是一種方法嗎? hasSerialize右側的表達式(lambda)將實際計算爲什麼?評估中的執行順序是什麼?在hasSeriaize中,auto會評估什麼?

請幫我理解這是我與這個掙扎了一個星期,但仍不能我的頭周圍。如果任何人能舉一個這樣的實際例子,將不勝感激。

感謝

回答

1

首先,該代碼使用boost::hana::is_valid - 請務必閱讀其文檔,瞭解它在做什麼。


是hasSerialize是一種方法?

否,它與一個lambda表達式初始化的變量。這是一個​​。


什麼是表達式(拉姆達)到hasSerialize的右側將計算爲實際?

下面的代碼...

auto hasSerialize = is_valid([](auto&& x) -> decltype(x.serialize()) { }); 

...將創建一個函數對象,當一個對象調用y將返回std::true_type如果y.serialize()是有效的表達式,std::false_type否則。例如:

struct Foo { }; 
struct Bar { void serialize() { } }; 

static_assert(!hasSerialize(std::declval<Foo>())); 
static_assert(hasSerialize(std::declval<Bar>())); 

這裏有一個簡單的可能實現的is_valid

template <typename TF> 
struct validity_checker 
{ 
    template <typename... Ts> 
    constexpr auto operator()(Ts... ts) 
    { 
     return std::is_callable< 
      TF(typename decltype(ts)::type...) 
     >{}; 
    } 
}; 

template <typename TF> 
constexpr auto is_valid(TF) 
{ 
    return validity_checker<TF>{}; 
} 

它只是使用std::is_callable看是否通用拉姆達拖得decltype可以與一些特定的參數調用。 如果尾隨decltype內的表達式是無效的一些特定的參數類型,拉姆達不調用。


is_callable可以在SFINAE友好的方式來實現如下,使用void_t

template <typename...> 
using void_t = void; 

template <typename, typename = void> 
struct is_callable : std::false_type { }; 

template <typename TF, class... Ts> 
struct is_callable<TF(Ts...), 
    void_t<decltype(std::declval<TF>()(std::declval<Ts>()...))>> 
    : std::true_type { }; 
+0

謝謝您的回答。我會盡量回答你的答案,並通過閱讀關於lamdas的更多內容來了解​​這一點(關閉,因爲我仍然沒有從你的鏈接中得到它)。一天後會回覆你。 –