2.3 基本元功能构建块
类型特征有两个普遍的习语:
- 使用给定值定义公共数据成员值
- 定义一个命名给定类型的公共成员 typedef 类型
令人惊讶的是,有一个标准实用程序提供前者 (
std::integral_constant
),但没有标准实用程序提供后者。type_identity
是这个实用程序。它是其他元功能可以简单继承的基本构建块。例如,remove_const
可以如下实现:template <typename T> struct remove_const : type_identity<T> {}; template <typename T> struct remove_const<T const> : type_identity<T> {};
它的实现很简单:
template<class T>
struct type_identity
{
using type = T;
};
因此,我尝试type_identity
在我的代码中广泛使用,包括Detection Idiom的个人实现:
namespace detail
{
template<class Default,
class AlwaysVoid,
template<class...>
class Op,
class... Args>
struct detector : type_identity<Default> // here
{
using value_t = std::false_type;
};
template<class Default, template<class...> class Op, class... Args>
struct detector<Default, std::void_t<Op<Args...>>, Op, Args...>
: type_identity<Op<Args...>> // here
{
using value_t = std::true_type;
};
} // namespace detail
// ......
它在任何地方都可以正常工作,直到我将 libcxx 的测试套件用于我自己的实现 is_destructible
,以下是失败案例:
struct ProtectedDestructor
{
protected:
~ProtectedDestructor()
{}
};
// ......
template<class T>
void
test_is_not_destructible()
{
static_assert(!is_destructible<T>::value, "");
// ......
}
// ......
test_is_not_destructible<ProtectedDestructor>();
现场演示:
prog.cc:83:47:错误:“~ProtectedDestructor”是“ProtectedDestructor”的受保护成员
使用 has_dtor = decltype(std::declval().~U()); ^ prog.cc:26:19:注意:在此处请求的模板类型别名“has_dtor”的实例化中
: type_identity<Op<Args...>> ^
prog.cc:45:1:注意:在模板类 'detail::detector 的实例化中
……
奇怪的是,一旦用 trival 替换type_identity
,using type = ......
编译器就没有错误,demo。对于其他琐碎的has_member
检查,type_identity
工作正常,演示。
所以,这里唯一的问题是,对于受保护的 dtor,type_identity
将强制 structdetail::detector
检查 dtor 的有效性,而using type = something
不会。
我认为解决方案很简单,只需删除type_identity
,然后 using type = something
直接使用,就像Walter E. Brown 的原始实现一样。但问题是:
为什么会type_idintity
在这里打破,而琐碎using type = something
却没有?