Как применить std :: is_convertible_v к множеству аргументов c? - PullRequest
2 голосов
/ 10 марта 2020

Я хотел бы проверить, что если список аргументов можно преобразовать в size_t или нет. Я думаю, что std::is_convertible_v - правильный инструмент от STL. Вот что, я думаю, должно быть (что неверно):

#include <type_traits>

template<typename... Args>
constexpr bool check_all_convertible ()
{
    return std::is_convertible_v<Args,size_t>;
}

Я наконец хочу использовать check_all_convertible() для включения другой функции:

template<typename... Args>
std::enable_if_t<check_all_convertible<Args...>(), void> 
    some_function (Args... args) {}

Вопрос

  • Как я могу использовать std::is_convertible_v для переменных c аргументов?
  • Вы предлагаете лучший подход из STL?

Я ценю любые предложения по улучшению код выше.

Ответы [ 3 ]

6 голосов
/ 10 марта 2020

Вы можете использовать выражение сгиба:

template<typename... Args>
std::enable_if_t<(std::is_convertible_v<Args,size_t> && ...)> 
some_function (Args... args) {}
2 голосов
/ 11 марта 2020

C ++ 20 решение (Да! Наконец-то у нас есть концепции !!!):

#include <concepts>

auto some_function(std::convertible_to<std::size_t> auto ... args)
{
}

Смотрите его вживую на godbolt .

The * Требуется 1008 *, потому что комитет обосновал, что без этого объявление будет обманчиво выглядеть как функция (но это шаблон). Бьярне думает, что они будут сожалеть об этом. В любом случае, мы должны все время набирать auto, потому что отныне мы не должны писать шаблоны без ограничений.

Для полноты здесь приведена более длинная версия (но я рекомендую краткую):

template <std::convertible_to<std::size_t>... Args>
auto some_function2(Args... args)
{
}

И более длинная версия:

template <class... Args>
    requires (std::convertible_to<Args, std::size_t> && ...)
auto some_function3(Args... args)
{
}
1 голос
/ 11 марта 2020

Как я выяснил, у вас есть поддержка C ++ 17, но в случае C ++ 11 / C ++ 14 вы можете сделать следующее (возможно, вам это понадобится в будущем):

template<
    typename    To,
    typename    From
    typename... Rest
> constexpr bool is_converible_variadic_impl()
{
    return \
        std::is_convertible<From, To>::value && 
        is_converible_variadic_impl<To, Rest...>();
}

template<
    typename To,
    typename From
> constexpr bool is_converible_variadic_impl()
{
    return std::is_convertible<From, To>::value;
}

/*************************************************/

template<
    typename    To,
    typename... From
> struct is_convertible_variadic
   : std::integral_constant<bool, is_converible_variadic_impl<To, From...>()>
{ };

template<
    typename    To,
    typename... From
> constexpr bool is_convertible_variadic_v = is_convertible_variadic<To, From...>::value;

Для size_t используйте его, как в следующем примере:

template<typename... Args>
std::enable_if_t<std::is_convertible_variadic_v<size_t, Args...> > 
some_function (Args... args) {}

Возможно, вводить тип «To» в начале (несоответствие с STL) параметров шаблона может быть непонятно, но я думаю, что это не так такая сложная задача это исправить:)

...