检查是否存在嵌套类型的别名并有条件设置类型别名

发布于 2025-01-22 16:17:41 字数 950 浏览 3 评论 0原文

我不知道如何根据这样的输入参数中的类型别名有条件地设置类型的别名。

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");

一个天真的尝试就像std ::条件&lt; std :: is_class&lt; t&gt; t :: type,type,t&gt;如果存在type> type type type 别名是先决条件,但远非安全,还没有检查is_alias_present&lt; t,type&gt;之类的检查。除此之外,t :: Type可能并不存在导致编译器错误的所有类型。

Apearthy std :: fastiment :: superiment :: is_detected 不幸的是,但不幸的是,不幸的是目前。

不确定是否像boost :: mp11boost :: hana这样的好方法是完成此操作的好方法。

I wonder how to conditionally set a type alias, based on the existance of a type alias in input argument like this.

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");

One naive attempt is like std::conditional<std::is_class<T>, T::type, T> if the existence of a type alias is a prerequisite, but is far from being safe, lacking a check for something like is_alias_present<T, type>. Besides that T::type is potentially not existing for all types resulting in a compiler error.

Apearently std::experimental::is_detected looks promising, but unfortunately not an option for now.

Not sure if metaprogramming libraries like boost::mp11 or boost::hana are a good approach to get that done.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

浮生未歇 2025-01-29 16:17:41

借助

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中的C ++ 20概念,您可以使用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
};

demo

With the help of C++20 concepts

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
};

In C++17, you can use void_t to detect the validity of 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
};

Demo

尤怨 2025-01-29 16:17:41

一种选择是像这样的作品中编写类型特征

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&lt; typeName t :: type&gt;然后丢弃了type_member的专业化,我们回到了非类型成员专业化。

One option is to write a type trait like

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>;

and then you would use it in wrapper like

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");
}

This works by leveraging SFINAE and if typename T::type is ill-formed in std::void_t<typename T::type> then that specialization of type_member is discarded and we fall back to the non-type member specialization.

祁梦 2025-01-29 16:17:41

有两件事,要检测存在的特征和懒惰的评估。

在C ++ 20中,可以使用需要轻松完成这些特征

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;
};

There are 2 things, the traits to detect presence, and the lazy evaluation.

In C++20, the traits can be done easily with requires

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

Then the lazy evaluation:

template <typename T> struct wrapper {
    using inner_t = std::conditional_t<has_type<T>, T, std::type_identity<T> >::type;
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文