Есть ли причина использовать std :: conunction / std :: disjunction вместо выражения сгиба над "&&" / "||"? - PullRequest
17 голосов
/ 14 марта 2019

Существуют ли какие-либо конкретные случаи, которые вы не можете правильно выполнить с std::conjunction / std::disjunction и не используете более «фундаментальное» (то есть языковое, а не библиотечное) выражение сгиба для && / ||?

Пример:

// func is enabled if all Ts... have the same type
template<typename T, typename... Ts>
std::enable_if_t<std::conjunction_v<std::is_same<T, Ts>...> >
func(T, Ts...) {
 // TODO something to show
}

против

// func is enabled if all Ts... have the same type
template<typename T, typename... Ts>
std::enable_if_t<(std::is_same<T, Ts> &&...)>
func(T, Ts...) {
 // TODO something to show
}

Версия с использованием выражения сгиба является более краткой и, как правило, более читаемой (хотя мнения могут отличаться по этому вопросу). Поэтому я не понимаю, почему он был добавлен в библиотеку вместе с выражениями свертки.

1 Ответ

23 голосов
/ 14 марта 2019

std::conjunction короткое замыкание ::value создание экземпляра, в то время как выражение сгиба - нет.Это означает, что, учитывая:

template <typename T> 
struct valid_except_void : std::false_type { };

template <> 
struct valid_except_void<void> { };

Будет скомпилировано следующее:

template <typename... Ts>
constexpr auto test = std::conjunction_v<valid_except_void<Ts>...>;

constexpr auto inst = test<int, void>;

Но следующее не будет:

template <typename... Ts>
constexpr auto test = (valid_except_void<Ts>::value && ...);

constexpr auto inst = test<int, void>;

живой пример на godbolt.org


От cppreference :

Соединение короткое замыкание: если естьаргумент типа шаблона Bi с bool(Bi::value) == false, затем создание экземпляра conjunction<B1, ..., BN>::value не требует создания экземпляра Bj::value для j > i.

...