【问题标题】:c++ variadic template: can't match functionc++ 可变参数模板:无法匹配函数
【发布时间】:2017-03-26 15:52:01
【问题描述】:

这是我的代码:

#include <iostream>
#include "Generator.h" // user-defined class

char getChar(Generator & generator)
{
    return generator.generateChar();
}

char getChar(int pos, const string & s)
{
    return s[pos];
}

template<typename... StringType>
void func(Generator & generator, StringType &&... str)
{
    char ch;
    int size = sizeof...(StringType);
    // lots of things to do
    if (size == 0)
    {
        ch = getChar(generator);
    }
    else
    {
        ch = getChar(1, std::forward<StringType>(str)...); // ERROR here
    }
}

int main(int argc, char ** argv)
{
    Generator generator;

    func(generator);
    func(generator, "abc");

    return 0;
}

一开始我只是重载了函数func,发现有很多类似的代码。所以我正在考虑使用可变参数模板来获得更好的设计。 (How to make a better design if two overload functions are similar)

但是不知道为什么会报错:

main.cpp:27:8: 错误:没有匹配的函数调用“getChar” ch = getChar(1, std::forward(str)...);

main.cpp:37:2:注意:在此处请求的函数模板特化“func”的实例化
函数(生成器);

main.cpp:6:6: 注意:候选函数不可行:第一个参数 char 没有从“int”到“Generator &”的已知转换
getChar(生成器和生成器)

main.cpp:11:6:注意:候选函数不可行:需要 2 个参数,但提供了 1 个 char getChar(int pos, const string & s)



顺便说一句,我可以设计一些避免使用 if...else...sizeof...(StringType) 一起使用的设计吗?

【问题讨论】:

    标签: c++ c++11 templates variadic-templates


    【解决方案1】:

    当一个模板被展开时,整个模板代码被展开,并且被编译为一个整体。

    让我们看看这里发生了什么:

    func(generator);
    

    在生成的模板生成函数中,size 将为 0,生成的函数变为:

    if (0 == 0)
    {
        ch = getChar(generator);
    }
    else
    {
        ch = getChar(1);
    }
    

    您的编译错误变得非常明显:getchar(1);getChar() 的任何重载实例都不匹配。 if 语句将始终评估为 true,而 else 部分将永远不会被执行的事实并不重要。 else 部分必须仍然是有效的 C++ 代码,它会被编译,并且只有在编译后才会被优化掉(也许)。而且不能编译,所以编译出错。

    现在回答了您的问题“我不知道为什么会出现错误”。现在你知道了。如何解决这个问题变成了一个不同的问题,答案是,根据具体情况,模板专业化和/或 SFINAE 的某种组合。

    看起来您问题中的示例是一个缩写示例(因为如果参数包有两个或多个参数,模板函数显然将永远无法工作)。这很好(并且 100% 符合展示最小、完整、可验证示例的精神),但提出所示代码的替代可编译版本可能无法回答您的真正问题。

    【讨论】:

      猜你喜欢
      • 2023-03-07
      • 2018-11-16
      • 2023-04-02
      • 2018-07-02
      • 2020-09-12
      • 1970-01-01
      • 1970-01-01
      • 2017-10-31
      相关资源
      最近更新 更多