c – 未作为最后一个参数传递时的模板参数包扣除

前端之家收集整理的这篇文章主要介绍了c – 未作为最后一个参数传递时的模板参数包扣除前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
请考虑以下代码
  1. #include <iostream>
  2. #include <functional>
  3.  
  4. template<typename... Args>
  5. void testfunc(const std::function<void (float,Args...,char)>& func)
  6. {
  7.  
  8. }
  9.  
  10. int main(int argc,char* argv[])
  11. {
  12. auto func = [](float,int,char) {};
  13. auto sfunc = static_cast<std::function<void (float,char)>>(func);
  14. testfunc<int>(sfunc);
  15.  
  16. return 0;
  17. }

我明确指定了类型,因为(https://stackoverflow.com/a/40476083):

When a parameter pack doesn’t appear last in the parameter
declaration,it is a non-deduced context. A non-deduced context means
that the template arguments have to be given explicitly.

MSVC成功编译它,而gcc和clang都拒绝代码

  1. source_file.cpp: In function int main(int,char**)’:
  2. source_file.cpp:14:24: error: no matching function for call to testfunc(std::function<void(float,char)>&)’
  3. testfunc<int>(sfunc);
  4. ^
  5. source_file.cpp:5:6: note: candidate: template<class ... Args> void testfunc(const std::function<void(float,Args ...,char)>&)
  6. void testfunc(const std::function<void (float,char)>& func)
  7. ^
  8. source_file.cpp:5:6: note: template argument deduction/substitution Failed:
  9. source_file.cpp:14:24: note: mismatched types char and int
  10. testfunc<int>(sfunc);
  11. ^
  12. source_file.cpp:14:24: note: std::function<void(float,char)>’ is not derived from const std::function<void(float,char)>’

现在让我们稍作改动 – 让我们从本地func中删除int参数,从而导致模板参数包变空:

  1. #include <iostream>
  2. #include <functional>
  3.  
  4. template<typename... Args>
  5. void testfunc(const std::function<void (float,char)>>(func);
  6. testfunc<>(sfunc);
  7.  
  8. return 0;
  9. }

这一次,所有三个编译器都拒绝代码不正确.
使用http://rextester.com/l/cpp_online_compiler_gcc和本地Visual Studio安装进行测试.

问题:

>第一种情况谁是正确的?
>如何实现预期效果 – 即,如何明确指定(可能为空)参数包?

解决方法

我们可以阻止扣除:
  1. template<typename... Args>
  2. void testfunc(const block_deduction<std::function<void (float,char)>>& func)

  1. template<class T>
  2. struct tag_t{using type=T;};
  3.  
  4. template<class T>
  5. using block_deduction=typename tag_t<T>::type;

现在Args ……处于非演绎的背景中.

你可以用SFINAE做更好的事情并省略char然后在Args的末尾测试char,但这看起来有点过分.

当gcc和clang不同意MSVC时,我会向甜甜圈打赌,MSVC不对.但我没有标准钻探确认.

猜你在找的C&C++相关文章