почему type_identity нарушает реализацию is_detected - PullRequest
0 голосов
/ 25 ноября 2018

p0887r1 :

2.3 Фундаментальный базовый метафункциональный блок

Существует два вездесущих идиома для типовых признаков:

  • defineОткрытое значение элемента данных с заданным значением
  • определяет открытый тип 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>();

live demo :

prog.cc: 83: 47: ошибка: '~ ProtectedDestructor' является защищенным членом'ProtectedDestructor'

с использованием has_dtor = decltype (std :: declval (). ~ U ());^ prog.cc:26:19: note: при создании экземпляра шаблона типа псевдоним has_dtor, запрашиваемый здесь

           : type_identity<Op<Args...>>
                            ^

prog.cc: 45: 1: note: при создании класса шаблона detail ::детектор

......

странно, что один раз заменив type_identity на тривал using type = ......, компилятор не имеет ошибок , demo .Для другой проверки has_member, type_identity работает нормально, demo .

Итак, единственная проблема здесь, для защищенного dtor, type_identity заставит struct detail::detectorпроверяйте действительность dtor, пока using type = something не будет.

Я думаю, что решение простое, просто удалите type_identity и используйте using type = something напрямую, как оригинальная реализация Уолтера Е. Брауна .Но вопрос в следующем:

почему type_idintity ломается здесь, а trival using type = something нет?

...