Построение поверх другого ответа , ниже вы можете найти решение с использованием SFINAE, как указано в вопросе с использованием enable_if
.
Это несколько сложнее, чем Первоначально я ожидал, что это так, потому что количество предоставленных аргументов для boost::mpl_vector_c
в частичной специализации шаблона не соответствует размеру mpl::vector
.
. Поэтому я определяю вспомогательную структуру, ниже которой позволяет выполнять логические операции 'и' над подмножеством предоставленного шаблона логических значений переменной c.
Если доступен c ++ 17, строки, помеченные комментарием c ++ 14 / c ++ 17 можно исключить. Если c ++ 14 недоступен, index_sequence может, например, быть заменен путем использования рекурсивного объявления #value в структуре и суффиксов _v
/ _t
, замененных на [...]::value/type
соответственно.
#include <boost/mpl/vector_c.hpp>
#include <tuple>
/// Helper struct which enables to evaluate a conjunction of a subset of a set of booleans.
template <typename IndexSequence, bool... v> struct PartialConjunction;
/// Parital template specialization
template <std::size_t... idx, bool... b>
struct PartialConjunction<std::index_sequence<idx...>, b...>
: std::integral_constant<
bool, (std::get<idx>(std::forward_as_tuple(b...)) && ...)> {};
/// 'Alias' for the value
template <std::size_t S, bool... v> constexpr auto PartialConjunction_v =
PartialConjunction<decltype(std::make_index_sequence<S>()), v...>::value;
/// Actual struct which holds the type of the vector in ::type if it meets the criterion
template <typename VecType, VecType N, typename MplVector> struct Same; //< c++14
//template <auto N, typename MplVector> struct Same; //< c++17
template <typename VecType, VecType N, long... a> struct Same<VecType, N, boost::mpl::vector_c<VecType, a...>> {// c++14
//template <typename VecType, VecType N, long... a> struct Same<N, boost::mpl::vector_c<VecType, a...>> { // c++17
using type = boost::mpl::vector_c<VecType, a...>;
static constexpr auto Size = typename type::size();
static constexpr auto value = PartialConjunction_v<Size, N == static_cast<VecType>(a)...>;
};
/// Alias for the type which performs SFINAE.
template <typename T, T N, typename VectorType, typename = std::enable_if_t<Same<T, N, VectorType>::value>> // c++14..
using Same_t = typename Same<T, N, VectorType>::type;
//template <auto N, typename VectorType, typename = std::enable_if_t<Same<N, VectorType>::value>> // c++17..
//using Same_t = typename Same<N, VectorType>::type;
int main() {
// For the c++17 version, the first 'int' in the parameter list can be omitted
//Same_t<int, 1, boost::mpl::vector_c<int, 1, 1, 2>> fails;
Same_t<int, 1, boost::mpl::vector_c<int, 1, 1, 1>> ok;
Same_t<int, 1, boost::mpl::vector_c<int, 1, 1>> okok;
Same_t<int, 1, boost::mpl::vector_c<int, 1>> okokok;
}
Пример кода можно найти здесь в CompilerExplorer.