Spec-Zone.ru › C++

std::conjunction

Определён в заголовке <type_traits>
template< class... B >
struct conjunction;
(начиная с C++17)

Формирует логическую конъюнкцию признаков типов B..., фактически выполняя логическое И над последовательностью признаков.

Специализация std::conjunction<B1, ..., BN> имеет открытый и однозначный базовый класс, который является

  • если sizeof...(B) == 0, std::true_type; в противном случае
  • первым типом Bi в B1, ..., BN, для которого bool(Bi::value) == false, или BN, если такого типа нет.

Имена членов базового класса, кроме conjunction и operator=, не скрываются и однозначно доступны в conjunction.

Конъюнкция вычисляется с коротким замыканием: если существует аргумент типа шаблона Bi, для которого bool(Bi::value) == false, то при инстанцировании conjunction<B1, ..., BN>::value не требуется инстанцирование Bj::value для j > i.

Если программа добавляет специализации для std::conjunction или std::conjunction_v, поведение не определено.

Параметры шаблона

B... - каждый аргумент шаблона Bi, для которого инстанцируется Bi::value, должен допускать использование в качестве базового класса и определять член value, преобразуемый в bool

Вспомогательный шаблон переменной

template< class... B >
constexpr bool conjunction_v = conjunction<B...>::value;
(начиная с C++17)

Возможная реализация

template<class...>
struct conjunction : std::true_type {};

template<class B1>
struct conjunction<B1> : B1 {};

template<class B1, class... Bn>
struct conjunction<B1, Bn...>
    : std::conditional_t<bool(B1::value), conjunction<Bn...>, B1> {};

Примечания

Специализация conjunction не обязательно наследуется ни от std::true_type, ни от std::false_type: она просто наследуется от первого B, значение ::value которого после явного преобразования в bool равно false, либо от самого последнего B, если все они преобразуются в true. Например, std::conjunction<std::integral_constant<int, 2>, std::integral_constant<int, 4>>::value — это 4.

Инстанцирование с коротким замыканием отличает conjunction от свёрточных выражений: свёрточное выражение, например (... && Bs::value), инстанцирует каждый B в Bs, тогда как std::conjunction_v<Bs...> прекращает инстанцирование, как только значение можно определить. Это особенно полезно, если последующий тип сложно инстанцировать или его инстанцирование с неподходящим типом может привести к серьёзной ошибке.

Макрос проверки поддержки Значение Стандарт Функция
__cpp_lib_logical_traits 201510L (C++17) Типовые свойства логических операторов

Пример

#include <iostream>
#include <type_traits>

// func is enabled if all Ts... have the same type as T
template<typename T, typename... Ts>
std::enable_if_t<std::conjunction_v<std::is_same<T, Ts>...>>
func(T, Ts...)
{
    std::cout << "All types in pack are the same.\n";
}

// otherwise
template<typename T, typename... Ts>
std::enable_if_t<!std::conjunction_v<std::is_same<T, Ts>...>>
func(T, Ts...)
{
    std::cout << "Not all types in pack are the same.\n";
}

template<typename T, typename... Ts>
constexpr bool all_types_are_same = std::conjunction_v<std::is_same<T, Ts>...>;

static_assert(all_types_are_same<int, int, int>);
static_assert(not all_types_are_same<int, int&, int>);

int main()
{
    func(1, 2, 3);
    func(1, 2, "hello!");
}

Вывод:

All types in pack are the same.
Not all types in pack are the same.

См. также

negation
(C++17)
метафункция логического НЕ
(шаблон класса)
disjunction
(C++17)
вариативная метафункция логического ИЛИ
(шаблон класса)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/types/conjunction

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API