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

模板参数包在Clang上失败,但不是VS 2015

诸彬郁
2023-03-14

我正在处理一个函数,该函数调用一个具有可变参数数的函数。它在Visual Studio 2015上编译并正常工作,但在Clang上编译失败。我准备了一个演示,展示了我要做的事情。我在Clang中遇到的错误是:

掠夺。cpp:在函数“int main()”中:prog。cpp:31:2:错误:调用“run(std::vector)”时没有匹配的函数

#include <functional>
#include <iostream>
#include <vector>
using namespace std;

template<int RepeatTimes, class ... mutrArgs>
void run(
    vector<int>& vec,
    const function<void(int&, mutrArgs ...)>& mutr,
    mutrArgs ... args
)
{
    for (int times{0} ; times < RepeatTimes ; ++times)
        for (auto& item : vec)
            mutr(item, args...);
}

void adder(int& i, const int& val)
{
    i += val;
}

int main()
{
    vector<int> v{0,1,2,3,4,5,6,7,8,9};
    const int addValue{4};
    run<2, const int&>(
        v,
        &adder,
        addValue
    );
    for (auto i : v)
        cout << i << " ";
    cout << endl;
    return 0;
}

共有2个答案

邵君植
2023-03-14

如果查看所有标准库算法函数,至少那些采用“谓词”(可调用对象)的函数会将该参数作为模板类型。

如果您这样做,它将生成:

template<int RepeatTimes, typename F, class ... mutrArgs>
void run(
    vector<int>& vec,
    F mutr,
    mutrArgs ... args
)
{
    ...
}

请参阅此处获取代码示例。请注意,您不需要提供所有模板参数,编译器可以推断它们。

羿博延
2023-03-14

运行

run<2, const int&>(v, &adder, addValue);

有两个地方可以推断出mutrArgs

>

  • addValue-

    用函数地址解决那个问题

    auto call_run = &run<2, const int&>;
    call_run(v, &adder, addValue);
    

    奇怪的是,clang不支持与gcc相反的内联用法:/

    (&run<2, const int&>)(v, &adder, addValue);
    

    如果要禁用扣减,可以将模板arg设置为不可扣减:

    template <typename T> struct identity { using type = T; };
    
    template <typename T> using non_deducible_t = typename identity<T>::type;
    

    然后呢

    template<int RepeatTimes, class ... mutrArgs>
    void run(
        std::vector<int>& vec,
        const std::function<void(int&, non_deducible_t<mutrArgs> ...)>& mutr,
        non_deducible_t<mutrArgs> ... args
    )
    

    演示

    即使在您的情况下,Joachim Pileborg建议的简单的类型名F似乎更好。

  •  类似资料:
    • 我已经编写了一个具有递归评估的可变参数模板函数。对于最后一个参数,我在没有可变参数包的情况下实现了专业化,并且一切正常。 现在我想把可变函数参数转换成模板参数。 这是我的尝试: gcc和clang报告了一个模糊的过载,并且无法使用空参数包在“专业化”和“可变参数”之间做出决定。 我尝试删除特化并检查可变参数模板中的包大小,但是如果没有特化,编译器就无法推断出参数“p”。

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

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

    • 下面的代码在g7.2.0中编译成功(编译标志是),但在clang 5.0.0中编译失败(使用相同的标志,)和vc 15.4(编译标志是): 哪种编译器行为符合标准?如何将该模板应用更改为在clang上编译? 叮当声错误消息: VC错误消息:

    • 这些代码如下: 使用G++4.8.2错误信息编译:

    • 在传递函数时,我遇到了这个模板演绎/替换问题。有人可以帮忙吗,我非常感谢: 以下是编译代码时的错误: 示例.cpp:在 'bool Region::setAllValues(D) 的实例化中