Неоднозначный вызов перегруженной функции в переменной функции шаблона

#c #c 11

#c #c 11

Вопрос:

Я использую переменную шаблонную функцию, где параметры функции не являются шаблонными типами.

Я получил ошибку компиляции:

Ошибка C2668 ‘_TailHelper’: неоднозначный вызов перегруженной функции

Вот это фрагмент кода.

 template <typename HEAD>
void _TailHelper(int) {
    std::cout << typeid(HEAD).name() << std::endl;
}

template <typename HEAD, typename ... TAILS>
void _TailHelper(int x) {
    _TailHelper<HEAD>(x);
    _TailHelper<TAILS...>(x);
}


int main(){
    _TailHelper<int,double>(2);
}
  

Комментарии:

1. Вы забыли объяснить, как вы компилируете, и полностью процитировать ошибку компилятора.

2. имена, начинающиеся с _ , за которыми следует заглавная буква, зарезервированы.

3. что должно _TailHelper<HEAD>(x); вызывать? Ваш компилятор не знает, и мы также не можем

4. Конечно, это неоднозначно, _TailHelper<int> соответствует обоим шаблонам, TAILS может быть пустым.

5. Кроме того, пожалуйста, не SHOUT делайте ничего, кроме MACRO_NAMES , и не используйте макросы. Если вы хотите соглашение, которое выделяет аргументы шаблона из других имен, попробуйте, например T_Head , и T_Tails или что-то еще, но нет ALL_CAPS .

Ответ №1:

Обе перегрузки совпадают с одним аргументом шаблона, поэтому вы должны отключить его. Например, так:

 #include <iostream>    
#include <typeinfo>

template <typename T>
void TailHelper(int) { 
    std::cout << typeid(T).name() << std::endl;
}

template <typename HEAD, typename ... TAILS>
typename std::enable_if<(sizeof...(TAILS) != 0)>::type
TailHelper(int x) {
    TailHelper<HEAD>(x);        
    TailHelper<TAILS...>(x);
}

int main() {
    TailHelper<int,double>(2);
}
  

Ответ №2:

Неоднозначный вызов исходит из этой строки:

_TailHelper<HEAD>(x);

этот вызов соответствует обеим функциям — первой и второй функции, второй параметр которой может ссылаться на ноль или более параметров шаблона.

Ответ №3:

В качестве альтернативы рекурсии вы можете «перебирать» свои переменные:

В C 17:

 template <typename... Ts>
void PrintTypes() {
    ((std::cout << typeid(Ts).name() << std::endl), ...);
}
  

В предыдущей версии это было менее элегантно, и вы могли бы использовать какой-нибудь трюк, как:

 template <typename... Ts>
void PrintTypes() {
    const int dummy[] = {0, ((std::cout << typeid(Ts).name() << std::endl), 0)...};
    static_cast<void>(dummy); // Avoid warning for unused variable
}