Как применить parameter pack (pack expansion) на enable_if (until C++20 SFINAE)?

Рейтинг: 2Ответов: 1Опубликовано: 12.04.2023

Основная проблема в том, что paremeter pack должен быть последним параметром в списке, а до него о Ts ещё ничего не известно. Но и при выносе enable_if за пределы параметров шаблона ничего не меняется. Вот:

template<typename T>
using RemoveCVR = std::remove_reference_t<std::remove_cv_t<T>>;
    
template<typename T1, typename T2>
static inline constexpr bool IsSimilar =
    std::is_same_v<RemoveCVR<T1>,RemoveCVR<T2>>;
    
template<
    typename... Ts,
    typename std::enable_if_t<IsSimilar<Ts,std::string>>...
>
void f();

template<
    typename std::enable_if_t<IsSimilar<Ts,std::string>>...,
    typename... Ts
>
void f();

template<typename... Ts>
typename std::enable_if_t<IsSimilar<Ts,std::string>>... f();

Есть ли способ?

Ответы

▲ 2Принят

Выносить за параметры шаблона следует правильно:

#include <type_traits>
#include <string>
#include <iostream>

template<typename T>
using RemoveCVR = std::remove_reference_t<std::remove_cv_t<T>>;
    
template<typename T1, typename T2>
static inline constexpr bool IsSimilar =
    std::is_same_v<RemoveCVR<T1>,RemoveCVR<T2>>;
    
template<typename... Ts>
std::enable_if_t<(IsSimilar<Ts,std::string> and...)> f()
{
    ::std::cout << "test\n";
}

template<typename... Ts>
std::enable_if_t<not (IsSimilar<Ts,std::string> and...)> f()
{
    ::std::cout << "test2\n";
}

int main()
{
    f<std::string>();
    f<int>();
    return 0;
}

test
test2

online compiler

A еще можно использовать if constexpr (IsSimilar<Ts,std::string> and ...).