首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >条件类型别名定义

条件类型别名定义
EN

Stack Overflow用户
提问于 2016-01-06 11:49:37
回答 1查看 1.3K关注 0票数 8

我有这样一个类型:

代码语言:javascript
复制
template<typename T>
struct wrapper
{
    using foo = typename T::foo;
    using bar = typename T::bar;
    using baz = typename T::baz;
    // More of those...
};

我希望定义foobarbaz和等效类型别名的条件是,只有当等效类型存在于T中时。使用std::conditional的解决方案允许在不存在时将其替换为其他类型,但当模板类型中不存在对应的类型时,我不知道如何确保它根本不存在。当wrapper<T>被实例化时,上面的代码会导致一个错误,如果T没有定义一个类型别名。

我不能让wrapper继承T,因为wrapper不应该做T能做的所有事情。此外,使用部分专门化会导致某种指数爆炸,并将很快变得不可维护。我可能会让foobar..。模板类型别名将std::enable_if注入到默认的模板参数中,但是用户将不得不编写wrapper<T>::foo<>wrapper<T>::bar<>而不是wrapper<T>::foowrapper<T>::bar等.我不想那样。

T中存在对应的类型别名时,是否有一种简单而可维护的方法来定义这样的类型别名?

EN

回答 1

Stack Overflow用户

发布于 2016-01-19 19:15:06

请注意,使用@TartanLlama使用void_t的答案是很好的。但是,在C++17中,很可能会有一些标准库助手,比如is_detected_v,它们将在幕后调用void_t

代码语言:javascript
复制
#include <experimental/type_traits>

// helpers to reduce boilerplate
template<class Tag>
struct empty_base {};

template<template<class> class Holder, template<class> class Op, class Arg>
using inject_or_t = std::conditional_t
<
    std::experimental::is_detected_v<Op, Arg>,
    Holder<Arg>,
    empty_base<Op<Arg>>
>;

// add detector + holder for every conditional nested type

template<class T>
using foo_t = typename T::foo;

template<class T>
struct foo_holder { using foo = foo_t<T>; };

template<class T>
using bar_t = typename T::bar;

template<class T>
struct bar_holder { using bar = bar_t<T>; };

template<class T>
using baz_t = typename T::baz;

template<class T>
struct baz_holder { using baz = baz_t<T>; };

// wrapper is now simply:

template<class T>
struct wrapper
:   inject_or_t<foo_holder, foo_t, T>
,   inject_or_t<bar_holder, bar_t, T>
,   inject_or_t<baz_holder, baz_t, T>
{};

struct Test
{
    using foo = int;
    using bar = int;
    using baz = int;
};

int main()
{
    static_assert(!std::experimental::is_detected_v<foo_t, wrapper<int>>);
    static_assert(!std::experimental::is_detected_v<bar_t, wrapper<int>>);
    static_assert(!std::experimental::is_detected_v<baz_t, wrapper<int>>);

    static_assert(std::experimental::is_detected_v<foo_t, wrapper<Test>>);
    static_assert(std::experimental::is_detected_v<bar_t, wrapper<Test>>);
    static_assert(std::experimental::is_detected_v<baz_t, wrapper<Test>>);
}

Live Example注意: his是libstdc++ 6.0SVN主干可以使用的一个非常罕见的例子(目前!)做一些libc++ 3.9svn主干无法做的事情。

这需要为每种注入类型添加一个检测器别名和一个持卡器结构,并且完全不需要宏包装器。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34632416

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档