Не удалось вывести аргумент шаблона для 'TYPE'

85
8

У меня есть следующий код, который отлично работает:


list <Politician> MakeList ( int num, ... ){
va_list arguments;
va_start ( arguments, num );
list <Politician> PoliticianList;
for ( int x = 0; x < num; x++ ) {
PoliticianList.push_back(va_arg (arguments, Politician));
}
va_end ( arguments );

return PoliticianList;
}


Однако при попытке сделать его общим:


template<class TYPE>
list <TYPE> MakeList ( int num, ... ){
va_list arguments;
va_start ( arguments, num );
list <TYPE> PoliticianList;
for ( int x = 0; x < num; x++ ) {
PoliticianList.push_back(va_arg (arguments, TYPE));
}
va_end ( arguments );

return PoliticianList;
}


При компиляции я получаю следующую ошибку:


error C2783: 'std::list<TYPE> MakeList(int,...)' : could not deduce template argument for 'TYPE'

Как я могу сделать его общим, так что мне не придется повторно реализовывать для разных объектов класса?

спросил(а) 2013-05-24T23:04:00+04:00 7 лет, 9 месяцев назад
1
Решение
85

Вам нужно явно указать аргумент шаблона для TYPE при вызове templated версии MakeList, потому что компилятор не знает, основываясь только на аргументах, которые вы предоставляете, что TYPE должно быть. Например, при следующем вызове:


MakeList<Politician>(3, politician1, politician2, politician3)

Компилятор не может определить, что такое TYPE. Если вы ожидаете, что он будет достаточно умным и вывести, что вы передаете объекты типа Politician в качестве аргументов, хорошо, что это не сработает: вариативные функции C-стиля просто не предоставляют эту информацию во время компиляции.


Однако в С++ 11 для этой цели вы можете использовать вариативные шаблоны, которые, помимо прочего, позволят вам не передавать число последующих аргументов в качестве первого аргумента. Вот возможный способ переписать свой вариационный MakeList():

namespace detail
{
template<typename T>
void MakeList(std::list<typename std::remove_reference<T>::type>& l, T&& elem)
{
l.push_back(std::forward<T>(elem));
}

template<typename T, typename... Ts>
void MakeList(
std::list<typename std::remove_reference<T>::type>& l,
T&& elem, Ts&&... elems)
{
l.push_back(std::forward<T>(elem));
MakeList(l, std::forward<Ts>(elems)...);
}
}

template<typename T, typename... Ts>
std::list<typename std::remove_reference<T>::type> MakeList(
T&& elem, Ts&&... elems)
{
std::list<typename std::remove_reference<T>::type> l;
detail::MakeList(l, std::forward<T>(elem), std::forward<Ts>(elems)...);
return l;
}


Затем вы можете использовать его следующим образом:


int main()
{
Politician p1{"John", "Smith"};
Politician p2{"Mike", "Black"};
Politician p3{"George", "White"};

std::list<Politician> myList = MakeList(p1, p2, p3);

for (auto const& p : myList)
{
std::cout << p.name << " " << p.surname << std::endl;
}
}


Вот живой пример.

ответил(а) 2013-05-24T23:17:00+04:00 7 лет, 9 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема