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
|
Шаблон вспомогательной переменной
<tbody> </tbody> template< class... B > inline 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 доступна, если все Ts... имеют тот же тип, что и T
template<typename T, typename... Ts>
std::enable_if_t<std::conjunction_v<std::is_same<T, Ts>...>>
func(T, Ts...)
{
std::cout << "все типы в пакете являются T\n";
}
// иначе
template<typename T, typename... Ts>
std::enable_if_t<!std::conjunction_v<std::is_same<T, Ts>...>>
func(T, Ts...)
{
std::cout << "не все типы в пакете являются T\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, "привет!");
}
Вывод:
все типы в пакете являются T
не все типы в пакете являются T
Смотрите также
(C++17) |
логическая метафункция НЕ (шаблон класса) |
(C++17) |
вариативная логическая метафункция ИЛИ (шаблон класса) |