简单的可变参数模板函数无法实例化

发布于 2024-11-30 14:56:31 字数 1136 浏览 1 评论 0原文

我知道 sizeof...(Args...) 产生 C++0x 打包模板参数列表中的类型数量,但我想根据其他功能来实现它演示目的,但它不会编译。

// 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()

它没有看到首先定义的基本情况。前向声明 templatenum_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]

我正在使用海湾合作委员会4.6。我怎样才能做到这一点?

谢谢。

I'm aware that sizeof...(Args...) yields the number of types in a C++0x packed template argument list, but I wanted to implement it in terms of other features for demonstation purposes, but it won't compile.

// 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> ();
}

This errors at *HERE* with

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

i.e. it's not seeing the base case which is defined first. Forward-declaring template<typename...T>num_args(); introduces ambiguity in overload resolution.

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]

I am using gcc 4.6. How can I make this work?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

祁梦 2024-12-07 14:56:31

您没有声明基本情况。您的 num_args 函数有一个无模板重载,但是当调用函数 num_args() 时,这永远不会被发现,原因很明显:它总是会尝试实例化一个函数模板。

不过,您可以专门您的函数模板来执行所需的操作。

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;
}

You didn’t declare a base case. You have a template-free overload of your num_args function but when calling a function num_args<T...>() this will never be found, for obvious reasons: it will always try to instantiate a function template.

You can however specialise your function template to perform the desired operation.

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

However, this won’t work either since here you’re specialising a parameterless function template and such a template doesn’t exist: your other function template num_args always has at least one argument, H.

In order to really make this work you need partial specialisations, and these only exist for class templates. So this is what you need here.

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;
}
遇见了你 2024-12-07 14:56:31

康拉德的答案应该可以帮助您继续下去,但我认为通常表达此类内容的更惯用方式是使用静态成员常量,所以我只想提出该解决方案:

#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::值。

Konrad's answer should get you going, but I think the more idiomatic way such things are usually expressed is with static member constants, so I just wanted to present that solution:

#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> { };

Then you get your argument pack size via arg_size<Args...>::value.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文