簡體   English   中英

SFINAE 用戶定義轉換算子

[英]SFINAE User-Defined-Conversion Operator

我正在嘗試使用自省設計的模板化用戶定義轉換。

在 C++20 中,我可以執行以下操作:

    template<typename T>
    operator T() const
    {
        if constexpr( requires { PFMeta<T>::from_cursor(*this); } )
        {
            return PFMeta<T>::from_cursor(*this);
        }
        else
        {
            T x;
            std::memcpy(&x, &data, sizeof(x));
            return x;
        }
    }

即,如果PFMeta<T>::from_cursor(const struct PFCursor&)則使用它,否則執行 memcpy。 (godbolt 中的更長示例: https://godbolt.org/z/abed1vsK3

我喜歡這種方法,但不幸的是,這個庫也需要在 C++17 上工作。

所以我一直在嘗試將 SFINAE 作為概念的替代方案,但這非常棘手。 我終於設法得到類似的東西,但使用模板化方法as不是用戶定義的轉換運算符本身:

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

template<typename T>
struct has_from_cursor<T, decltype( PFMeta<T>::from_cursor(std::declval<struct PFCursor>()), void() ) > : std::true_type { };

// ...

    template<class T>
    std::enable_if_t<has_from_cursor<T>::value, T> as() const
    {
        return PFMeta<T>::from_cursor(*this);
    }

    template<class T>
    std::enable_if_t<!has_from_cursor<T>::value, T> as() const
    {
        T x;
        std::memcpy(&x, &data, sizeof(x));
        return x;
    }

我嘗試了以下編譯但不起作用的方法(我無法使用它):

    template<typename T>
    operator std::enable_if_t<has_from_cursor<T>::value, T>() const
    {
        return PFMeta<T>::from_cursor(*this);
    }

    template<typename T>
    operator std::enable_if_t<!has_from_cursor<T>::value, T>() const
    {
        T x;
        std::memcpy(&x, &data, sizeof(x));
        return x;
    }

更長的例子: https://godbolt.org/z/5r9Mbo18h

所以兩個問題:

  • 對於用戶定義的轉換運算符,我可以有效地使用 C++17 中的 SFINAE 來有效地處理概念嗎?
  • 有沒有比類型特征和enable_if更簡單的方法來執行as方法? 理想情況下,我想做一些事情,比如定義默認的模板化方法,然后在條件存在時有一個首選的專業化(即有一個元 class 和一個 static 成員 ZC1C425268E68385D1AB5074C17A 定義)

謝謝!

對於用戶定義的轉換運算符,我可以有效地使用 C++17 中的 SFINAE 來有效地處理概念嗎?

if constepr考慮 C++17 支持。 鑒於您已經開發了從std::true_typestd::false_type false_type 繼承的has_from_cursor自定義類型特征,您可以將它用於if constexp

我的意思是(注意:代碼未經測試)

template<typename T>
operator T() const
{ // .............VVVVVVVVVVVVVVVVVVVVVVVVV
    if constexpr( has_from_cursos<T>::value )
    {
        return PFMeta<T>::from_cursor(*this);
    }
    else
    {
        T x;
        std::memcpy(&x, &data, sizeof(x));
        return x;
    }
}

有沒有比類型特征和 enable_if 更簡單的方法來執行 as 方法? 理想情況下,我想做一些事情,比如定義默認的模板化方法,然后在條件存在時有一個首選的專業化(即有一個元 class 和一個 static 成員 ZC1C425268E68385D1AB5074C17A 定義)

我想你可以嘗試標簽調度......

我的意思是從operator T()中調用 'as()' 並帶有一個額外的int參數

template<typename T>
operator T() const
{ return as<T>(0); } // <-- call as() with a int

其中有一個特定於from_cursos class 的as() ,它接收未使用的int並且只是通過decltype()啟用/禁用 SFINAE

template <typename T>  // ........accept an int; best match
decltype(PFMeta<T>::from_cursor(*this)) as (int) const
 { return PFMeta<T>::from_cursor(*this); }

和一個通用as() ,接收很long

template <typename T>
T as (long) const // <-- accept a long; worst match
 {
   T x;
   std::memcpy(&x, &data, sizeof(x));
   return x;
 }

訣竅是未使用的參數:一個int

當啟用專用as()時,如果首選,因為接受int所以是更好的匹配。

當專用as()被禁用時,將通用as()保持為比沒有更好的匹配。

暫無
暫無

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

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