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

Template Parameter Pack Fails on Clang but not VS 2015

本文关键字:失败 VS 2015 但在 Clang 参数      更新时间:2023-10-16

>我正在研究一个函数,该函数调用具有可变参数数量的提供的函数。它在Visual Studio 2015上编译并正常工作,但在Clang上无法编译。我准备了一个演示,展示了我正在尝试做什么。 我在 Clang 中遇到的错误是:

prog.cpp:在函数 'int main()' 中: prog.cpp:31:2: 错误: 无匹配 函数调用 'run(std::vector&, void ()(int&, const int&), const int&)' ); ^ Prog.cpp:7:6: 注: 候选人: 模板无效 run(std::vector&, const std::function&, 穆特阿格斯... 无效运行( ^ prog.cpp:7:6: 注意:模板参数推导/替换失败: prog.cpp:31:2: 注意:不匹配的类型'const std::function' 和 'void ()(int&, const int&)' );

#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;
}

run<2, const int&>只陈述第一个参数,但不会停用演绎。

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

有2个地方可以推断mutrArgs

  • addValue -> mutrArgs = { const int& }

  • &adder这不是一个std::function,所以失败了。

获取函数地址可解决此问题

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

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

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

如果你想禁用扣除,你可以让你的模板参数不可推导:

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建议的简单typename F似乎更好。

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

如果你做同样的事情,它将构建:

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

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