Тип, чтобы проверить, что все типы в пакете параметров являются копируемыми
Мне нужна черта типа, чтобы проверить, являются ли все типы в пакете параметров конструктивными. Это то, что я сделал до сих пор. Основная функция содержит некоторые тестовые примеры, чтобы проверить функциональность.
#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 после пакета параметров в списке шаблонов не работает. Понятия не имею. Кто-нибудь имеет хороший совет, как решить проблему?
Ответы
Ответ 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;