簡體   English   中英

檢查是否存在嵌套類型別名並有條件地設置類型別名

[英]Check for existence of nested type alias and conditionally set type alias

我想知道如何根據這樣的輸入參數中類型別名的存在有條件地設置類型別名。

struct a { using type = int; }

template <typename T> struct wrapper {
    using inner_t = ???how???; // if T::type exists, use T::type, else T
};

static_assert(std::is_same<wrapper<int>::inner_t, int>, "expected int");
static_assert(std::is_same<wrapper<a>::inner_t, int>, "expected inner type: int");

如果type別名的存在是先決條件,那么一種天真的嘗試就像std::conditional<std::is_class<T>, T::type, T> ,但遠非安全,缺少對is_alias_present<T, type>類的檢查is_alias_present<T, type> 除此之外, T::type可能並非對所有類型都存在,從而導致編譯器錯誤。

Apearently std::experimental::is_detected看起來很有希望,但不幸的是現在不是一個選項。

不確定像boost::mp11boost::hana這樣的元編程庫是否是完成該任務的好方法。

借助 C++20 概念

template<class T>
struct innter {
  using type = T;
};

template<class T>
  requires requires { typename T::type; }
struct innter<T> {
  using type = T::type;
};

template <typename T> 
struct wrapper {
  using innter_t = innter<T>::type; // if T::type exists, use T::type, else T
};

在C++17中,可以使用void_t來檢測T::type的合法性

#include <type_traits>

template<class T, class = void>
struct innter {
  using type = T;
};

template<class T>
struct innter<T, std::void_t<typename T::type>> {
  using type = typename T::type;
};

template <typename T> 
struct wrapper {
  using innter_t = typename innter<T>::type; // if T::type exists, use T::type, else T
};

演示

一種選擇是編寫類型特征,例如

template <typename T, typename = void >
struct type_member
{
    using type = T;
};
 
template <typename T >
struct type_member<T, std::void_t<typename T::type>>
{
    using type = typename T::type;
};

template <typename T >
using type_member_t = type_member<T>;

然后你會在包裝器中使用它

template <typename T>
struct wrapper
{
    using type = type_member_t<T>::type;
};

int main()
{
    static_assert(std::is_same_v<typename wrapper<int>::type, int>, "expected int");
    static_assert(std::is_same_v<typename wrapper<a>::type, int>, "expected inner type: int");
}

這通過利用 SFINAE 來實現,如果typename T::typestd::void_t<typename T::type>中格式錯誤,那么type_member的特化將被丟棄,我們回退到非類型成員特化。

有兩件事,檢測存在的特征和惰性評估。

在 C++20 中,可以使用requires輕松完成特征

template <typename T>
concept has_type = requires { typename T::type; }

然后懶惰評價:

template <typename T> struct wrapper {
    using inner_t = std::conditional_t<has_type<T>, T, std::type_identity<T> >::type;
};

暫無
暫無

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

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