Подтвердить что ты не робот

Тип, чтобы проверить, что все типы в пакете параметров являются копируемыми

Мне нужна черта типа, чтобы проверить, являются ли все типы в пакете параметров конструктивными. Это то, что я сделал до сих пор. Основная функция содержит некоторые тестовые примеры, чтобы проверить функциональность.

#include <type_traits>
#include <string>
#include <memory> 

template <class... Args0toN>
struct areCopyConstructible;

template<>
struct areCopyConstructible<> : std::true_type {};

template <class Arg0, class... Args1toN, class std::enable_if< !std::is_copy_constructible<Arg0>::value>::type* = nullptr >
struct areCopyConstructible : std::false_type {};

template <class Arg0, class... Args1toN, class std::enable_if< std::is_copy_constructible<Arg0>::value>::type* = nullptr >
struct areCopyConstructible : areCopyConstructible<Args1toN...> {};

int main()
{
  static_assert(areCopyConstructible<>::value, "failed");
  static_assert(areCopyConstructible<int>::value, "failed");
  static_assert(areCopyConstructible<int, std::string>::value, "failed");
  static_assert(!areCopyConstructible<std::unique_ptr<int> >::value, "failed");
  static_assert(!areCopyConstructible<int, std::unique_ptr<int> >::value, "failed");
  static_assert(!areCopyConstructible<std::unique_ptr<int>, int >::value, "failed");
}

Ссылка на живой пример

Моя идея состояла в том, чтобы проверить рекурсивно, является ли элемент главы пакета конструктивным или нет и дальше, с хвостом. К сожалению, у меня нет этой идеи для компиляции. Мои знания о вариативных шаблонах не очень продвинуты. Я думаю, что enable-if после пакета параметров в списке шаблонов не работает. Понятия не имею. Кто-нибудь имеет хороший совет, как решить проблему?

4b9b3361

Ответ 1

Сначала определите повторно используемую утилиту для проверки того, является ли каждый предикат в пакете истинным:

template<typename... Conds>
  struct and_
  : std::true_type
  { };

template<typename Cond, typename... Conds>
  struct and_<Cond, Conds...>
  : std::conditional<Cond::value, and_<Conds...>, std::false_type>::type
  { };

Тогда тривиально использовать это с is_copy_constructible (или любым другим унарным типом):

template<typename... T>
  using areCopyConstructible = and_<std::is_copy_constructible<T>...>;

Одним из преимуществ определения and_, как это, является то, что он замыкает, т.е. останавливает создание экземпляра is_copy_constructible для остальной части пакета после первого ложного результата.

Ответ 2

Я предпочитаю трюк @Columbo bool_pack. Сначала шаблон, чтобы проверить, что все в пакете параметров bool true:

template<bool...> struct bool_pack;
template<bool... bs> 
using all_true = std::is_same<bool_pack<bs..., true>, bool_pack<true, bs...>>;

Тогда

template<class... Ts>
using areCopyConstructible = all_true<std::is_copy_constructible<Ts>::value...>;

Ответ 3

Если наследование от std::true_type или std::false_type не имеет значения, то это можно сделать простым способом без SFINAE:

template <class... Args0toN>
struct areCopyConstructible;

template<>
struct areCopyConstructible<> : std::true_type {};

template <class Arg0, class... Args1toN>
struct areCopyConstructible<Arg0, Args1toN...> {
    static constexpr bool value = std::is_copy_constructible<Arg0>::value
        && areCopyConstructible<Args1toN...>::value;
};

Если вы хотите наследовать от std::true_type или std::false_type, вы можете использовать std::conditional:

template <class... Args0toN>
struct areCopyConstructible;

template<>
struct areCopyConstructible<> : std::true_type {};

template <class Arg0, class... Args1toN>
struct areCopyConstructible<Arg0, Args1toN...> : 
    std::conditional<std::is_copy_constructible<Arg0>::value,
        areCopyConstructible<Args1toN...>,
        std::false_type
    >::type
{};

Ответ 4

Я знаю, что это старый вопрос, но поскольку у нас скоро будет С++ 17, я рекомендую взглянуть на std:: conj. С его помощью вы могли бы написать что-то вроде этого

template <typename ...Args>
using areCopyConstructible = typename std::conjunction<std::is_copy_constructible<Args>...>::type;