2

p0887r1

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_identityusing 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却没有?

4

0 回答 0