【问题标题】:Compilation Error on Recursive Variadic Template Function递归可变参数模板函数的编译错误
【发布时间】:2011-06-29 11:37:22
【问题描述】:

我在 Code::Blocks 中准备了一个简单的可变参数模板测试,但出现错误:

没有匹配的函数调用'OutputSizes()'

这是我的源代码:

#include <iostream>
#include <typeinfo>

using namespace std;

template <typename FirstDatatype, typename... DatatypeList>
void OutputSizes()
{
    std::cout << typeid(FirstDatatype).name() << ": " << sizeof(FirstDatatype) << std::endl;
    OutputSizes<DatatypeList...>();
}

int main()
{
    OutputSizes<char, int, long int>();
    return 0;
}

我正在使用带有-std=C++0x 的 GNU GCC。使用-std=gnu++0x 没有区别。

【问题讨论】:

    标签: c++ recursion c++11 codeblocks variadic


    【解决方案1】:

    以下是消除基本情况歧义的方法:

    #include <iostream>
    #include <typeinfo>
    
    template <typename FirstDatatype>
    void OutputSizes()
    {
        std::cout << typeid(FirstDatatype).name() << ": " << sizeof(FirstDatatype) << std::endl;
    }
    
    template <typename FirstDatatype, typename SecondDatatype, typename... DatatypeList>
    void OutputSizes()
    {
        OutputSizes<FirstDatatype>()
        OutputSizes<SecondDatatype, DatatypeList...>();
    }
    
    int main()
    {
        OutputSizes<char, int, long int>();
    }
    

    【讨论】:

    • 我想知道这是否可以在没有模板的三参数版本的情况下工作?
    • 三个参数 OutputSizes 应该调用单个参数一个以减少代码重复。
    • Doug Gregor(可变参数模板背后的主力军)最近提交了该领域的核心问题。我不够了解它是否会影响或改变这个用例(对不起)。该问题尚未分配编号,因此我无法向您指出。
    • 一开始我以为第二个模板可能是&lt;typename FirstDatatype, typename... DatatypeList&gt;,而偏序可以解决调用OutputSizes&lt;char&gt;的歧义,但是偏序将无法解决这个问题,因为没有函数参数 :( @Howard,他是否将该问题发布到某处的核心列表中?请注意,这并非特定于可变参数模板。例如,template&lt;typename T&gt; void f(); template&lt;typename T, typename U = void&gt; void f(); 然后对 f&lt;int&gt; 的调用同样模棱两可,我认为.
    【解决方案2】:

    这是因为您没有提供基本案例。您提取了可变参数模板参数的最后一个数据类型,然后您尝试将空可变参数参数与采用类型和可变参数参数的函数匹配。当可变参数为空时,您需要提供“基本情况”。

    using namespace std;
    
    template <typename FirstDatatype, typename... DatatypeList>
    void OutputSizes()
    {
        std::cout << typeid(FirstDatatype).name() << ": " << sizeof(FirstDatatype) << std::endl;
        OutputSizes<DatatypeList...>();
    }
    
    template<typename... DataTypeList>
    void OutputSizes() // We're called when there's no template arguments
                       // left in the pack
    {
    }
    
    int main()
    {
        OutputSizes<char, int, long int>();
        return 0;
    }
    

    编辑:我在这里展示的多零重载实际上仅在您也根据模板类型采用实际运行时参数时才有效。如果您只直接采用模板参数,则可以使用 Howard Hinnant 的回答中所示的二合一递归。

    【讨论】:

    • 我想我知道你的意思,但你能举个例子吗?我尝试仅使用 template &lt;typename Datatype&gt; 对其进行重载,但出现了模棱两可的重载错误。
    • @Maxpm:我不是可变参数模板方面的专家,因为我的编译器不支持它们,但我相信上面应该可以编译。
    • 我认为在这里使用术语“基类”会令人困惑。也许“递归终止条件”会更好。
    • 我无法编译上述内容。你能确保它有效吗?
    • 此代码无法编译:“对重载函数的模糊调用”。尝试了 3 种不同的编译器。
    猜你喜欢
    • 2015-07-18
    • 2019-07-27
    • 1970-01-01
    • 1970-01-01
    • 2016-12-11
    • 1970-01-01
    • 2018-02-12
    • 2017-02-23
    • 1970-01-01
    相关资源
    最近更新 更多