Как определить перегрузки на основе enable_if_t - PullRequest
2 голосов
/ 21 октября 2019

Я хотел написать комбинацию шаблонов из 2 перегрузок, как показано в коде ниже, я хочу сделать другой процесс для 2 жанров объектов. при компиляции я получил эти ошибки:

// Error    C2672   'info': no matching overloaded function found
// and
// // Error C2783   'void info(StrType)': could not deduce template argument for '__formal'

код:


/// With this commented out, compile fails, while with it uncommented, all cals get 
// in to this void template.
//template<typename T/*,
//typename = void*/>
//void info(T s) {
//
//}

template <typename StrType,
    std::enable_if_t<std::is_convertible_v<std::string, StrType>, bool> = false
>
void info(StrType s) {
    std::cout <<"str: "<< s << std::endl;
}


template<typename IntType,
    std::enable_if_t<std::is_same_v<    
    typename std::remove_reference_t<typename std::remove_cv<IntType>>  , 
    int
    >, bool> = false
>
void info(IntType s) {
    std::cout <<"int: "<< s + s << std::endl;
}

int main() {
    info("31");  // Error   C2672   'info': no matching overloaded function found
// and
// // Error C2783   'void info(StrType)': could not deduce template argument for '__formal'

    info((int)111);  // Same complain as above.
}

Я ожидал, что выходные данные будут str: 31 int: 111, но компиляция не удалась, жалуясь: ошибка C2672 'info': не найдено соответствующей перегруженной функции

Ответы [ 2 ]

4 голосов
/ 21 октября 2019

Обратите внимание, что для std::is_convertible 1-й шаблонный параметр равен From, 2-й - To, поэтому измените порядок аргументов шаблона с

template <typename StrType,
    std::enable_if_t<std::is_convertible_v<std::string, StrType>, bool> = false
>
void info(StrType s)

на

template <typename StrType,
    std::enable_if_t<std::is_convertible_v<StrType, std::string>, bool> = false
//                                         ^^^^^^^^^^^^^^^^^^^^
>
void info(StrType s)

Для 2-й перегрузки вы должны получить type от std::remove_cv, чтобы не использовать себя напрямую;поэтому измените

template<typename IntType,
    std::enable_if_t<std::is_same_v<    
    typename std::remove_reference_t<typename std::remove_cv<IntType>>  , 
    int
    >, bool> = false
>
void info(IntType s) {

на

template<typename IntType,
    std::enable_if_t<std::is_same_v<    
    typename std::remove_reference_t<typename std::remove_cv<IntType>::type>  , 
    //                                                               ^^^^^^
    int
    >, bool> = false
>
void info(IntType s) {

или (начиная с C ++ 14)

template<typename IntType,
    std::enable_if_t<std::is_same_v<    
    typename std::remove_reference_t<std::remove_cv_t<IntType>>  , 
    //                                             ^^
    int
    >, bool> = false
>
void info(IntType s) {

LIVE

1 голос
/ 21 октября 2019

Использование if constexpr может сделать ваш код проще, компактнее и, что более важно, более читабельным:

#include <type_traits>
#include <iostream>

template < typename T >
void info( T s )
{
    if constexpr( std::is_convertible_v< T, std::string > )
    {
        std::cout <<"str: "<< s << std::endl;
    }
    else if constexpr ( std::is_same_v< std::remove_reference_t< std::remove_cv_t< T > >, int > )
    {
        std::cout <<"int: "<< s + s << std::endl;
    }
    else
    {
        std::cout << "unknown type";
    }
}

int main() {
    info("31"); 
    info((int)111);
    info(1.1);
}
...