Специализация шаблона для пустого пакета параметров - PullRequest
13 голосов
/ 22 июня 2011

У меня есть функция шаблона variadic, которая вызывает себя, чтобы определить наибольшее число в списке (составленном из шаблонизированных аргументов).Я пытаюсь сделать специализацию для случая, когда пакет параметров пуст, поэтому я могу просто вернуть число в начале списка, но я не знаю, как это сделать.Я только знакомлюсь с вариадическими шаблонами и специализацией шаблонов, но это то, что я имею до сих пор:

#include <string>
#include <iostream>

using namespace std;

template <int N, int... N2>
int tmax() {
    return N > tmax<N2...>() ? N : tmax<N2...>();
}

template <int N>
int tmax() {
    return N;
}

int main() {
    cout << tmax<32, 43, 54, 12, 23, 34>();
}

Однако, это приводит к следующей ошибке:

test.cpp: In function ‘int tmax() [with int N = 34, int ...N2 = {}]’:
test.cpp:9:45:   instantiated from ‘int tmax() [with int N = 23, int ...N2 = {34}]’
test.cpp:9:45:   instantiated from ‘int tmax() [with int N = 12, int ...N2 = {23, 34}]’
test.cpp:9:45:   instantiated from ‘int tmax() [with int N = 54, int ...N2 = {12, 23, 34}]’
test.cpp:9:45:   instantiated from ‘int tmax() [with int N = 43, int ...N2 = {54, 12, 23, 34}]’
test.cpp:9:45:   instantiated from ‘int tmax() [with int N = 32, int ...N2 = {43, 54, 12, 23, 34}]’
test.cpp:18:39:   instantiated from here
test.cpp:9:45: error: no matching function for call to ‘tmax()’
test.cpp:9:45: error: no matching function for call to ‘tmax()’

У меня также естьпопробовал это, просто чтобы посмотреть, сработает ли это (хотя он вводит число 0 в список случайным образом, чтобы он никогда не мог вернуть число меньше 0):

template <int N, int... N2>
int tmax() {
    return N > tmax<N2...>() ? N : tmax<N2...>();
}

template <>
int tmax<>() {
    return 0;
}

Однако в дополнение к ошибкам, упомянутым выше, я получаю эту ошибку:

error: template-id ‘tmax<>’ for ‘int tmax()’ does not match any template declaration

Так что я должен сделать, чтобы это работало?

Я использую g ++ 4.5.2 с-std=c++0x флаг.

Ответы [ 3 ]

25 голосов
/ 22 июня 2011

Я вижу две ошибки, используя clang .

  1. Сначала перегрузка принимает один int.

  2. Makeвещи однозначные для списков длины 1. Вспомните, что списки с переменными значениями могут иметь нулевой размер, и когда они имеют место, мне кажется, что у вас есть неоднозначность.

    #include <iostream>
    
    using namespace std;
    
    template <int N>
    int tmax() {
        return N;
    }
    
    template <int N, int N1, int... N2>
    int tmax() {
        return N > tmax<N1, N2...>() ? N : tmax<N1, N2...>();
    }
    
    int main() {
        cout << tmax<32, 43, 54, 12, 23, 34>();
    }
    

    54

5 голосов
/ 22 июня 2011

Лично я предпочел бы использовать статические члены класса, а не функции для такого рода вещей:

template <int... N> struct max;
template <int N, int... M> struct max<N, M...> {
  static const int value = max<N, max<M...>::value>::value;
};    
template <int N, int M> struct max<N, M> {
  static const int value = N > M ? N : M;
};

int main()
{
  return max<1,2,3>::value;
}

Обновление: Используя предложение ildjarn, вот менее подробная версия:

#include <type_traits>
template <int... N> struct max;
template <int N, int... M> struct max<N, M...>
  : std::integral_constant<int, max<N, max<M...>::value>::value> { };
template <int N, int M> struct max<N, M>
  : std::integral_constant<int, (N > M ? N : M)> { };
0 голосов
/ 22 июня 2011

Поскольку вы не можете частично специализировать функции, вам нужно обернуть свою функциональность:

template<int Head, int... Tail>
struct Tmax{
  static int do(){
    return Head > Tmax<Tail...>::do() ? Head : Tmax<Tail...>::do();
  }
};

template<int N>
struct Tmax<N>{
  static int do(){
    return N;
  }
};

template<int... Numbers>
int tmax(){
  return Tmax<Numbers...>::do();
}
...