Template Parameter Pack Fails on Clang but not VS 2015
我正在处理一个函数,它用变量数的参数调用一个提供的函数。它在Visual Studio 2015上编译并正常工作,但未能在Clang上编译。我准备了一个演示,展示我正在做什么。我遇到的错误是:
prog.cpp: In function 'int main()': prog.cpp:31:2: error: no matching
function for call to 'run(std::vector&, void ()(int&, const
int&), const int&)' ); ^ prog.cpp:7:6: note: candidate:
template void
run(std::vector&, const std::function&,
mutrArgs ...) void run(
^ prog.cpp:7:6: note: template argument deduction/substitution failed: prog.cpp:31:2: note: mismatched types 'const
std::function' and 'void ()(int&, const
int&)' );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #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; } |
1 | run<2, const int&>(v, &adder, addValue); |
有2个地方可以推断
addValue ->mutrArgs ={ const int& } 。&adder ,不是std::function ,所以失败了。
解决这个问题
1 2 | auto call_run = &run<2, const int&>; call_run(v, &adder, addValue); |
奇怪的是,clang不支持与gcc相反的内联用法:/
1 | (&run<2, const int&>)(v, &adder, addValue); |
如果要禁用扣除,可以使模板arg不可扣除:
1 2 3 | template <typename T> struct identity { using type = T; }; template <typename T> using non_deducible_t = typename identity<T>::type; |
然后
1 2 3 4 5 6 | 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 ) |
演示
即使在你的例子中,约阿希姆·皮尔伯格建议的一个简单的
如果您查看所有标准库算法函数,至少那些采用"谓词"(可调用对象)的函数,它们将该参数作为模板类型。
如果您这样做,它将生成:
1 2 3 4 5 6 7 8 9 | template<int RepeatTimes, typename F, class ... mutrArgs> void run( vector<int>& vec, F mutr, mutrArgs ... args ) { ... } |
有关代码的示例,请参见此处。注意,您不需要提供所有模板参数,编译器可以推断出它们。