c++ - 条件类型别名定义

标签 c++ templates c++14 template-meta-programming sfinae

我有这样的类型:

template<typename T>
struct wrapper
{
    using foo = typename T::foo;
    using bar = typename T::bar;
    using baz = typename T::baz;
    // More of those...
};

我想要foo , bar , baz当且仅当 T 中存在等效类型时,才定义等效类型别名.使用 std::conditional 的解决方案允许在它不存在时用其他东西替换它,但是当模板类型中不存在相应类型时,我不知道如何确保它根本不存在。当 wrapper<T> 时,上面的代码会导致错误如果 T 被实例化没有定义类型别名之一。

我做不到wrapper继承自 T因为wrapper不应该做所有事情 T可以做。此外,使用部分特化会导致某种指数爆炸,并很快变得无法维护。我可能会做 foo , bar ... 模板类型别名以注入(inject) std::enable_if在默认模板参数中,但用户必须编写 wrapper<T>::foo<> , wrapper<T>::bar<>而不是 wrapper<T>::foo , wrapper<T>::bar等等...我不想这样。

有没有一种简单但可维护的方法来定义这样一个类型别名,只有当相应的类型别名存在于T中时? ?

最佳答案

你可以定义 check_foo , check_barcheck_baz只有类型存在的特征,然后从 wrapper 中的所有特征继承:

template <typename T, typename=void> 
struct check_foo{};

template <typename T> 
struct check_foo<T, void_t<typename T::foo>> { 
    using foo = typename T::foo; 
};

// ditto for bar, baz, etc.

template <typename T>
struct wrapper :
    check_foo<T>,
    check_bar<T>,
    check_baz<T>
{ };

它是每种类型的一个额外结构,但肯定比您提到的指数版本更可取。如果你适本地反常,你甚至可以把它变成一个宏:

#define DEFINE_CHECKER(NAME) \
    template <typename T, typename=void> struct check_##NAME{}; \
    template <typename T> struct check_##NAME<T,void_t<typename T::NAME>> \
    { using NAME = typename T::NAME; };

DEFINE_CHECKER(foo)
DEFINE_CHECKER(bar)
DEFINE_CHECKER(baz)

可怕,我知道,但我认为如果你真的想要,你可能需要付出那个代价wrapper<T>::bar而不是 wrapper<T>::bar<> .如果你使用宏版本,添加一个新类型将意味着一个新的 DEFINE_CHECKER(newname)并添加 check_newname<T>到包装器继承列表。可能会更糟。

Live Demo

关于c++ - 条件类型别名定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34632416/

相关文章:

c++ - 实例化特定模板特化时断言

c++ - 为什么 lambda 函数默认删除推导的返回类型引用?

c++ - 模板函数中具有单个可选参数和默认值的函数

c++ - 尽管右侧出现异常,但 C++ 中的赋值仍然存在

c++ - 为什么 vector<Data*>::iterator 有效而 vector<Data*>*::iterator 无效?

c++ - 如何使用 const 成员变量设置数组大小?

c++ - 与模板类 : Compile error 成为 friend

c++ - 如何在 C++ 中实现 "virtual template function"

c++ - 未处理的异常排序递归

javascript - 网页模板与从头开始构建