Умнее is_copy_constructible для обработки контейнеров - PullRequest
0 голосов
/ 22 апреля 2020

Я пытаюсь написать свою собственную версию std :: is_copy_constructible, которая будет возвращать false для контейнеров типов только для перемещения.

Я уже нашел этот ответ , описывающий, как сделать эта работа для определенного c типа контейнера. Теперь я пытаюсь расширить это, чтобы работать для любого контейнера. Для моих целей я определяю «контейнер» для обозначения любого класса, который имеет член «value_type». Чтобы определить, есть ли у класса член 'value_type', я использую вариант этого этого ответа .

Итак, в принципе, сейчас у меня есть следующее:

template <typename T, typename = void>
struct has_value_type : std::false_type {};
template <typename T>
struct has_value_type<T, decltype(std::declval<T>().value_type, void())> : std::true_type {};

для определения, имеет ли класс член value_type, и это:

template <template <typename> class test, typename T>
struct smart_test : test<T> {};
template <template <typename> class test, typename T, typename A>
struct smart_test<test, std::vector<T, A>> : smart_test<test, T> {};
template <typename T>
using smart_is_copy_constructible = smart_test<std::is_copy_constructible, T>;

для определения smart_is_copy_constructible, который работает правильно для векторов и неконтейнерных типов.

Я хочу объедините их, чтобы создать версию smart_is_copy_constructible, которая работает правильно для всех типов контейнеров (типов с элементом value_type). Я подозреваю, что мне нужно каким-то образом использовать std :: enable_if с моей структурой has_value_type, но это мой первый опыт метапрограммирования шаблонов, и я не уверен, как действовать дальше.

Моя лучшая догадка, так далеко было попробовать это

template <template <typename> class test, typename T>
struct smart_test<test, std::enable_if_t<has_value_type<T>::value> : smart_test<test, typename T::value_type> {};

вместо второго объявления из предыдущего блока кода (который определяет версию smart_test, специализирующуюся на векторе), но это не скомпилируется.

Any помощь будет принята с благодарностью!

1 Ответ

1 голос
/ 22 апреля 2020

Да, std::enable_if_t сделает это:

// I'd recommend following the standard library's naming convention
template<typename T, typename = void>
struct smart_is_copy_constructible : std::is_copy_constructible<T> { };
template<typename T>
struct smart_is_copy_constructible<T, std::enable_if_t<has_value_type<T>::value>> : std::is_copy_constructible<typename T::value_type> { };

template<typename T>
constexpr bool smart_is_copy_constructible_v = smart_is_copy_constructible<T>::value;

Godbolt

Но has_value_type в основном излишне. Ваша реализация не работает, и реализация, которую я дал в комментариях, достаточно короткая, чтобы встроить ее (хотя, как предполагает Николь Болас, вы можете захотеть сделать has_value_type более сложным):

template<typename T, typename = void>
struct smart_is_copy_constructible : std::is_copy_constructible<T> { };
template<typename T>
struct smart_is_copy_constructible<T, std::void_t<typename T::value_type>> : std::is_copy_constructible<typename T::value_type> { };

Godbolt

(исправленное has_value_type, использованное в первом примере:

template <typename T, typename = void>
struct has_value_type : std::false_type {};
template <typename T>
struct has_value_type<T, std::void_t<typename T::value_type>> : std::true_type {};

)

...