Функция перегрузки с несколькими определениями шаблонов невозможна? - PullRequest
0 голосов
/ 11 октября 2018

Я попробовал это:

template<typename P, typename = std::enable_if_t<std::is_arithmetic<P>::value>>
void f(std::vector<P>* a) {
    // body for arithmetic P
}

template<typename P, typename = std::enable_if_t<std::is_class<P>::value>>
void f(std::vector<P>* a) {
    // body for class P
}

Я думал, что это перегрузит f, поскольку условия являются взаимоисключающими, но обнаружил, что он не компилируется: "шаблон функции уже определен".

Что делать вместо этого, если я хочу, чтобы тело функции f(std::vector<P>*) зависело от того, является ли P арифметическим?

Ответы [ 2 ]

0 голосов
/ 11 октября 2018

Документация std::enable_if на cppreference.com гласит:

Распространенной ошибкой является объявление двух шаблонов функций, которые отличаются только аргументами шаблона по умолчанию.Это недопустимо, поскольку аргументы шаблона по умолчанию не являются частью сигнатуры шаблона функции , а объявление двух разных шаблонов функций с одной и той же сигнатурой недопустимо.

Примеры на этой же странице показываютпохожая на вашу ситуацию, и решите ее, изменив шаблон на одну из перегрузок, сохранив ту же сигнатуру для самих функций:

// #4, enabled via a template parameter
template<class T,
         typename std::enable_if<
             !std::is_trivially_destructible<T>{} &&
             (std::is_class<T>{} || std::is_union<T>{}),
            int>::type = 0>
void destroy(T* t)
{
    std::cout << "destroying non-trivially destructible T\n";
    t->~T();
}

// #5, enabled via a template parameter
template<class T,
    typename = std::enable_if_t<std::is_array<T>::value> >
void destroy(T* t) // note, function signature is unmodified
{
    for(std::size_t i = 0; i < std::extent<T>::value; ++i) {
        destroy((*t)[i]);
    }
}
/*
template<class T,
    typename = std::enable_if_t<std::is_void<T>::value> >
void destroy(T* t){} // error: has the same signature with #5
*/

Итак, вы можете сделать что-то похожее в своем коде:

template<typename P, std::enable_if_t<std::is_arithmetic<P>::value, int> = 0>
void f(std::vector<P>* a)
{
    // body for arithmetic P
}

template<typename P, typename = std::enable_if_t<std::is_class<P>::value>>
void f(std::vector<P>* a)
{
    // body for class P
}

Демонстрация в реальном времени

0 голосов
/ 11 октября 2018

Использовать диспетчеризацию тегов, например или аналогично:

void f_helper(std::vector<P>* a, std::true_type) {
    /* implementation for arithmetic type P */
}

void f_helper(std::vector<P>* a, std::false_type) {
    /* implementation for class type P */
}

void f(std::vector<P>* a) {
    return f_helper(a, std::is_arithmetic<P>{});
}
...