Этот код не компилируется: «неоднозначный вызов перегруженной функции». Пробовал с 3 разными компиляторами.

готовил простой шаблонный тест в Code :: Blocks, но получаю сообщение об ошибке:

Нет подходящей функции для вызова функции «OutputSizes ()»

Вот мой исходный код:

#include <iostream>
#include <typeinfo>

using namespace std;

template <typename FirstDatatype, typename... DatatypeList>
void OutputSizes()
{
    std::cout << typeid(FirstDatatype).name() << ": " << sizeof(FirstDatatype) << std::endl;
    OutputSizes<DatatypeList...>();
}

int main()
{
    OutputSizes<char, int, long int>();
    return 0;
}

Я использую GNU GCC с-std=C++0x, С помощью-std=gnu++0x не имеет значения.

Ответы на вопрос(2)

что вы не предоставили базовый случай. Вы извлекли последний тип данных параметра шаблона переменной, а затем попытались сопоставить пустой параметр переменной функции, принимающей тип и параметр переменной. Вам нужно указать «базовый случай», когда параметр переменной пуст.

using namespace std;

template <typename FirstDatatype, typename... DatatypeList>
void OutputSizes()
{
    std::cout << typeid(FirstDatatype).name() << ": " << sizeof(FirstDatatype) << std::endl;
    OutputSizes<DatatypeList...>();
}

template<typename... DataTypeList>
void OutputSizes() // We're called when there's no template arguments
                   // left in the pack
{
}

int main()
{
    OutputSizes<char, int, long int>();
    return 0;
}

Изменить: перегрузки с многими нулями, которые я показал здесь, на самом деле работают, только когда вы берете фактические аргументы времени выполнения, тоже основанные на типах шаблонов. Если вы берете только параметры шаблона напрямую, вы должны использовать рекурсию два-один, как показано в ответе Говарда Хиннанта.

 Omnifarious18 февр. 2011 г., 01:32
Я думаю, что использование термина «базовый класс» здесь сбивает с толку. Возможно, «условие завершения рекурсии» было бы лучше.
 Puppy18 февр. 2011 г., 00:26
@Maxpm: Я не эксперт по вариационным шаблонам, так как мой компилятор их не поддерживает, но я считаю, что вышесказанное должно скомпилироваться.
 Casey Rodarmor24 февр. 2012 г., 20:51
Я не могу получить выше, чтобы скомпилировать. Не могли бы вы убедиться, что это работает?
 Maxpm18 февр. 2011 г., 00:21
Я думаю, я знаю, что вы имеете в виду, но не могли бы вы привести пример? Я пытался перегрузить его простоtemplate <typename Datatype> но получил неоднозначные ошибки перегрузки.
 Vladimir Reshetnikov04 мар. 2018 г., 01:22
Этот код не компилируется: «неоднозначный вызов перегруженной функции». Пробовал с 3 разными компиляторами.
Решение Вопроса

Вот как вы устраняете неоднозначность базового варианта:

#include <iostream>
#include <typeinfo>

template <typename FirstDatatype>
void OutputSizes()
{
    std::cout << typeid(FirstDatatype).name() << ": " << sizeof(FirstDatatype) << std::endl;
}

template <typename FirstDatatype, typename SecondDatatype, typename... DatatypeList>
void OutputSizes()
{
    OutputSizes<FirstDatatype>()
    OutputSizes<SecondDatatype, DatatypeList...>();
}

int main()
{
    OutputSizes<char, int, long int>();
}
 Howard Hinnant18 февр. 2011 г., 04:47
Даг Грегор (основная сила, стоящая за вариационными шаблонами) недавно представил основной вопрос в этой области. Я не обладаю достаточными знаниями, чтобы знать, влияет ли это или изменяет этот вариант использования или нет (извините). Вопросу еще не присвоен номер, поэтому я не могу указать вам на него.
 Omnifarious18 февр. 2011 г., 02:02
OutputSizes с тремя аргументами должен вызывать один аргумент один, чтобы уменьшить дублирование кода.
 Omnifarious18 февр. 2011 г., 01:52
Интересно, возможно ли это сделать работу без версии шаблона с тремя аргументами?
 Johannes Schaub - litb20 февр. 2011 г., 18:06
Сначала я подумал, что второй шаблон может быть<typename FirstDatatype, typename... DatatypeList>и что частичное упорядочение решило бы двусмысленность с призывом кOutputSizes<char>, но частичное упорядочение не сможет решить эту проблему, так как нет никаких параметров функции :( @Howard, он где-то публиковал эту проблему в основном списке? Обратите внимание, что это не относится к шаблонам с переменными параметрами. Напримерtemplate<typename T> void f(); template<typename T, typename U = void> void f(); а затем звонок вf<int> Я думаю, это так же неоднозначно.

Ваш ответ на вопрос