gpt4 book ai didi

c++ - 为没有模板参数的可变模板递归创建基本情况

转载 作者:行者123 更新时间:2023-12-04 12:19:13 40 4
gpt4 key购买 nike

我正在尝试将递归与可变参数模板一起使用。我希望基本情况具有零模板参数。在查看了以前问题的 stackoverflow 答案后,我发现了对这个问题的两种回应:

  • 你不应该专门化模板函数。 Herb Sutter 在这里写道:http://www.gotw.ca/publications/mill17.htm
  • 您使用 template <typename = void> template <typename T = void> .例如,这里的第一个答案:How to write a variadic template recursive function?

  • 我试图在我的问题中使用解决方案 (2),但收到错误。这是一个最小的、可重现的示例:
    #include <iostream>

    template<typename = void> // base case
    int NumArguments() {
    return 0;
    }

    template<typename FirstArg, typename... RemainingArgs>
    int NumArguments() {
    return 1 + NumArguments<RemainingArgs...>();
    }
    class A {
    public:
    A() {}
    };

    int main() {
    std::cout << NumArguments<A>();
    return 0;
    }
    在 Microsoft Visual C++20 中编译给出了错误:
     error C2668: 'NumArguments': ambiguous call to overloaded function
    message : could be 'int NumArguments<A,>(void)'
    message : or 'int NumArguments<A>(void)'
    message : while trying to match the argument list '()'
    这个错误信息是什么意思?如何使用可变参数模板为递归创建零参数基本情况?
    编辑:评论中要求更完整地描述我的问题。问题真的是问题标题,而不是“我如何让我的代码工作?”,但我还没有编译我的代码,所以我决定分享它。 NumArguments是另一个函数的替代 ComputeSize作为输入 Args并返回 std::size_t .
        template<typename = void>
    constexpr std::size_t ComputeSize() {
    return 0;
    }

    template<typename FirstArg, typename... RemainingArgs>
    constexpr std::size_t ComputeSize() {
    return FuncReturnSize<FirstArg>() + ComputeSize<RemainingArgs...>();
    }
    Arg 的可能列表s 在 Args在编译之前是有限且已知的。 FuncReturnSize对于这些 Args 中的每一个都过载了.例如,两个可能的“重载”(?)是
    template <typename T>
    requires ((requires (T t) { { t.Func()} -> std::same_as<double>; }) || (requires (T t) { { t.Func() } -> std::same_as<std::vector<double>>; }))
    constexpr std::size_t FuncReturnSize() {
    return 1;
    }

    template <typename T>
    requires requires (T t) { { t.Func() } -> is_std_array_concept<>; }
    constexpr std::size_t FuncReturnSize() {
    return std::tuple_size_v<decltype(std::declval<T&>().Func())>;
    }
    概念 is_std_array_concept<>应该检查 t.Func() 的返回值是否是一些大小的数组。我还不确定它是否有效。它定义为
        template<class T>
    struct is_std_array : std::false_type {};
    template<class T, std::size_t N>
    struct is_std_array<std::array<T, N>> : std::true_type {};
    template<class T>
    struct is_std_array<T const> : is_std_array<T> {};
    template<class T>
    struct is_std_array<T volatile> : is_std_array<T> {};
    template<class T>
    struct is_std_array<T volatile const> : is_std_array<T> {};

    template<typename T>
    concept is_std_array_concept = is_std_array<T>::value;
    我希望所有这些计算都在编译时完成,所以我定义了
    template<std::size_t N>
    std::size_t CompilerCompute() {
    return N;
    }
    我现在应该可以 ComputeSize在编译时像这样:
    CompilerCompute<ComputeSize<Args...>()>()

    最佳答案

    错误消息的意思正是它所说的,调用是模棱两可的。

    template<typename = void> // base case
    constexpr int NumArguments() {
    return 0;
    }
    这不是一个接受 0 个参数的模板函数,这是一个接受一个默认参数的模板函数(所以如果没有指定参数,它是无效的)。这意味着 NumArguments<A>()是对这个函数的一个完全有效的调用。
    但是, NumArguments<A>()也是对带有空可变参数包的可变参数重载的完全有效调用(错误消息中列出的 NumArguments<A,>() 重载)。
    您的案例与链接示例的不同之处在于,在链接示例中,可变参数重载以 int 为模板。 s,不是类型,所以没有歧义。我在这里复制了该实现:
    template<class none = void>
    constexpr int f()
    {
    return 0;
    }
    template<int First, int... Rest>
    constexpr int f()
    {
    return First + f<Rest...>();
    }
    int main()
    {
    f<1, 2, 3>();
    return 0;
    }
    注意, f 的第二次重载是一个可变参数模板,其中每个模板参数必须是 int值(value)。调用 f<A>()如果 A 是类型,则不会匹配该重载,因此可以避免歧义。
    不可能声明一个零参数的模板函数,所以你不走运。但是,您可以将其转换为类模板,因为类模板可以部分特化。
    template <class ...Args> 
    struct NumArguments;

    template <>
    struct NumArguments<> {
    static constexpr int value = 0;
    };

    template <class T, class ...Args>
    struct NumArguments<T, Args...> {
    static constexpr int value = 1 + NumArguments<Args...>::value;
    };
    当然,这个特定的实现可以简化为使用 sizeof... ,但 OP 表示他们的实际用例更为复杂。

    关于c++ - 为没有模板参数的可变模板递归创建基本情况,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68041036/

    40 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com