我有这样的类型:
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_bar
和 check_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>
到包装器继承列表。可能会更糟。
关于c++ - 条件类型别名定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34632416/