簡體   English   中英

有沒有一種方法可以將模板的替換失敗轉換為bool值(true / false)或標簽(std :: true_type / std :: false_type)

[英]is there a way to convert a template's substitution failure into a bool value (true/false) or tags (std::true_type/std::false_type)

我正在以C ++ 17風格在SFINAE上“玩”一點,並且我試圖實現一種結果,在該結果中,替換失敗而不是僅導致編譯器移至下一種情況,而是導致了“編譯器”(進行了這種嘗試的類)(通過false / std::false_type )報告替換失敗,然后編譯器移至下一種情況。

我目前的嘗試歸結為這樣的事情:

template <typename T>
class logic_value
{
    static constexpr bool result = std::is_same<
        std::enable_if_t<T, std::true_type>,
        std::true_type>;
};

template <typename T>
inline constexpr bool lv = logic_value<T>::result;

(用法示例:)

template <typename T>
std::enable_if_t<
    lv<decltype(std::declval<T>() + std::declval<T>())> /* has plus operator */ 
    && 
    (lv<decltype(std::declval<T>().func_foo())> || lv<decltype(std::declval<T>().func_bar())>) /*has either func_foo() or func_bar() */ 
    &&
    lv<T&> /* can have a reference */
    && 
    (!lv<decltype(std::declval<T>().func_foobar())>) /* does NOT have a func_foobar() */
, T> const & Ioo(T const &);

但是它不像我想象的那樣起作用...://當我使用logic not! )運算符來確保測試類型中的某些內容不存在時,尤其棘手。

這樣做的方法是使用檢測慣用語,您希望使用適當的別名進行is_detected

在您的特定情況下:

template <typename T> using has_plus_t = decltype(std::declval<T>() + std::declval<T>());
template <typename T> using func_foo_t = decltype(std::declval<T>().func_foo());
template <typename T> using func_bar_t = decltype(std::declval<T>().func_bar());
template <typename T> using func_foobar_t = decltype(std::declval<T>().func_foobar());

template <typename T>
enable_if_t<
    is_detected_v<has_plus_t, T>
    && 
    (is_detected_v<func_foo_t, T> || is_detected_v<func_bar_t, T>)
    &&
    is_detected_v<add_lvalue_reference_t, T>
    && 
    !is_detected_v<func_foobar_t, T>
, T> const & Ioo(T const &);

您無法在這種情況下擁有要測試的表達式,因為一旦失敗,整個事情就會失敗。您的邏輯允許並要求某些表達式失敗-因此,您需要控制所有這些表達式的實例化。 這就是檢測慣用語的目的。

logical_value的問題是,在發生替換錯誤的情況下,您不向編譯器提供替代路徑。

我做這些事情是這樣的:

#include <utility>
#include <array>

template<typename T, typename U>
constexpr auto check_addition(int) -> decltype(std::declval<T>() + std::declval<U>() , std::true_type{});

template<typename T, typename U>
constexpr std::false_type check_addition(...);

template<typename T, typename U>
constexpr bool can_add = decltype(check_addition<T, U>(0))::value;

int main() {

    static_assert(can_add<int, float>);
    static_assert(!can_add<std::string, float>);

}

這個想法是利用兩個重載,一個重載特定類型的參數(在我的例子中為int ),另一個重載省略號。 當我們以int作為參數調用該重載函數時,編譯器將首先在必須執行所需檢查的地方檢查int重載。

逗號運算符用於提供true_type作為返回類型,以確保檢查成功完成。

如果第一個重載SFINAE失敗,則選擇第二個重載,該重載始終返回false_type

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM