当前位置: 首页 > 知识库问答 >
问题:

C 可变参数模板推导失败

林蕴藉
2023-03-14

我已经编写了一个具有递归评估的可变参数模板函数。对于最后一个参数,我在没有可变参数包的情况下实现了专业化,并且一切正常。

现在我想把可变函数参数转换成模板参数。

这是我的尝试:

template<typename N, int p> // specialization
N constexpr myadd(const N &n)
{
    return n + p;
}

template<typename N, int p, int ... v> // variadic
N constexpr myadd(const N &n)
{
    return myadd<N, v...>(n) + p;
}

int testfun()
{
    return myadd<int, 2>(7);
}

gcc和clang报告了一个模糊的过载,并且无法使用空参数包在“专业化”和“可变参数”之间做出决定。

我尝试删除特化并检查可变参数模板中的包大小,但是如果没有特化,编译器就无法推断出参数“p”。

共有2个答案

艾茂学
2023-03-14

参数包确实可以为空。您可以通过更改特化来处理不添加任何内容的情况来避免歧义:

template<typename N> // specialization
N constexpr myadd(const N &n)
{
    return n;
}

template<typename N, N p, N ... v> // variadic
N constexpr myadd(const N &n)
{
    return myadd<N, v...>(n) + p;
}

对于C 17,您可以通过使用折叠表达式来简化这一点:

template<typename N, N ... v> // variadic
N constexpr myadd(const N &n)
{
    return (v + ... + n);
}
瞿健
2023-03-14

正如这个答案所指出的,可变参数包确实可以是空的。但是您可以使用SFINAE专门化非空可变参数包的情况。

例如:

#include <iostream>
#include <type_traits>

template<typename N, int p> // specialization
N constexpr myadd(const N &n)
{
    std::cout << "specialization" << std::endl;
    return n + p;
}

template<typename N, int p, int ... v, class = std::enable_if_t<(sizeof...(v) > 0)>> // variadic
N constexpr myadd(const N &n)
{
    std::cout << "variadic" << std::endl;
    return myadd<N, v...>(n) + p;
}

int main()
{
    std::cout <<  myadd<int, 2>(7) << std::endl;
    std::cout <<  myadd<int, 2, 4>(7) << std::endl;
    
    return 0;
}

在科里鲁现场观看。

 类似资料:
  • 受这个答案的启发,我生成了这段代码,其输出取决于编译器: 如果使用 GCC 11 编译,调用

  • 在C++11之前,类模板和函数模板只能含有固定数量的模板参数。C++11增强了模板功能,允许模板定义中包含0到任意个模板参数,这就是可变参数模板。可变参数模板的加入使得C++11的功能变得更加强大,而由此也带来了许多神奇的用法。 可变参数模板 可变参数模板和普通模板的语义是一样的,只是写法上稍有区别,声明可变参数模板时需要在typename或class后面带上省略号...: template<ty

  • 我创建了一个模板类,其中构造函数采用std::function对象。第一个模板参数指示该函数的返回值。第二个参数定义该函数的参数类型。 关于使用函数std::function 它尝试使用基本版本。但第二个参数当然丢失了。如果我指定它编译的模板参数。 那么,为什么选择基本模板作为executorSpecialization2呢?甚至可以在这里对void使用类型推断,而不需要传递模板参数吗? 谢啦

  • 使用以下代码生成时 生成以下诊断(代码后): 诊断: 有趣的部分不是关于歧义错误本身(这不是这里主要关注的问题)。有趣的是,当仅使用函数名调用fun时,第一个fun的模板参数F被解析为纯函数类型double(double),而第二个fun的模板参数F被解析为更期望的函数指针类型。 然而,当我们将调用<代码>乐趣(测试) 更改为<代码>乐趣( 这种行为似乎是所有Clang和GCC(以及Visual

  • 我正在尝试编写一个简单的模板,我可以使用该模板对带有单个参数的函数进行记忆: 但我得到了一个错误: 错误:没有匹配函数来调用“备忘录(双精度)” 注:候选人是: 注意:模板OUT记忆(IN) 注意:模板参数扣除/替换失败: 为什么编译失败? 实际上,当我指定所有模板参数时,我不明白为什么模板参数推导/替换会发生。 我使用的是gcc版本4.7.2(未启用C 11) PS:模板的错误比我最初意识到的要

  • 以下是我的代码:< br > 一开始我只是重载了函数,发现有很多类似的代码。所以我正在考虑使用可变参数模板来获得更好的设计。(如果两个重载函数相似,如何做出更好的设计) 但是我不知道为什么会有错误:< br > main.cpp:27: 8:错误:没有匹配函数调用'getChar'ch=getChar(1, std::forward(str)...); 主要的cpp:37:2:注意:在函数模板专门