Простая функция шаблонов не может мгновенно - PullRequest
4 голосов
/ 18 августа 2011

Мне известно, что sizeof...(Args...) возвращает количество типов в списке аргументов упакованного шаблона C ++ 0x, но я хотел реализовать его с точки зрения других возможностей для целей демонтации, но он не будет компилироваться.1002 *

// This is not a solution -- overload ambiguity.
// template <typename... Args> size_t num_args ();          // Line 7
// template <>
constexpr size_t num_args ()
{
    return 0;
}

template <typename H, typename... T>
constexpr size_t num_args ()                                // Line 16
{
    return 1 + num_args <T...> (); // *HERE*
}

int main ()
{
    std :: cout << num_args <int, int, int> ();
}

Это ошибка при *HERE* с

No matching function call to ...
... candidate is template<class H, class ... T> size_t num_args()

, то есть он не видит базовый вариант, который определен первым.Объявление вперед template<typename...T>num_args(); вносит неоднозначность в разрешение перегрузки.

x.cpp:30:45: note: candidates are:
x.cpp:7:36: note: size_t num_args() [with Args = {int, float, char}, size_t = long unsigned int]
x.cpp:16:9: note: size_t num_args() [with H = int, T = {float, char}, size_t = long unsigned int]

Я использую gcc 4.6.Как я могу сделать эту работу?

Спасибо.

Ответы [ 2 ]

7 голосов
/ 18 августа 2011

Вы не объявили базовый случай. У вас есть перегрузка без шаблона вашей num_args функции, но при вызове функции num_args<T...>() это никогда не будет найдено по понятным причинам: она всегда будет пытаться создать экземпляр функции template .

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

template <>
constexpr size_t num_args<>()
{
    return 0;
}

Однако это также не сработает, поскольку здесь вы специализируете шаблон функции без параметров, а такой шаблон не существует: ваш другой шаблон функции num_args всегда имеет хотя бы один аргумент, H.

Чтобы действительно сделать эту работу, вам нужны частичные специализации, и они существуют только для шаблонов классов. Так что это то, что вам нужно здесь.

template <typename T>
struct num_args_t;

template <>
struct num_args_t {
    static size_t const value = 0;
};

template <typename H, typename T...>
struct num_args_t {
    static size_t const value = num_args_t<T...>::value + 1;
};

template <typename T...>
constexpr size_t num_args() {
    return num_args_t<T...>::value;
}
4 голосов
/ 18 августа 2011

Ответ Конрада должен помочь вам, но я думаю, что более идиоматический способ, которым такие вещи обычно выражаются, - это статические члены-константы, поэтому я просто хотел представить это решение:

#include <type_traits>

template <typename...> struct arg_size;  // no primary definition needed

template <typename T, typename ...Args> struct arg_size<T, Args...>
  : public std::integral_constant<std::size_t, 1 + arg_size<Args...>::value> { };

template <> struct arg_size<>
  : public std::integral_constant<std::size_t, 0> { };

Тогда вы получитеразмер пакета аргументов через arg_size<Args...>::value.

...