c – 在C 11标准中是否指定std :: begin(Container \u0026\u0026)返回const_iterator?

前端之家收集整理的这篇文章主要介绍了c – 在C 11标准中是否指定std :: begin(Container \u0026\u0026)返回const_iterator?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
这是相关代码链接
  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4. #include <type_traits>
  5.  
  6. int main()
  7. {
  8. std::vector<int> v{1,2,3,4,5};
  9. auto iter = begin(std::move(v));
  10. if(std::is_const<typename std::remove_reference<decltype(*iter)>::type>::value)
  11. std::cout<<"is const\n";
  12. return 0;
  13. }@H_301_3@
  14. http://coliru.stacked-crooked.com/a/253c6373befe8e50

  15. 我遇到了这种行为,因为在带有std :: begindecltype表达式中有一个declval< Container>(). gccclang都返回迭代器,在解除引用时会产生const引用.它可能是有意义的,因为r值引用通常绑定到您不想变异的过期对象.但是,我找不到任何关于此的文件来确定它是否符合标准.我找不到Container :: begin()的begin()或ref-qualified重载的任何相关重载.

  16. 更新:答案澄清了正在发生的事情,但相互作用可能很微妙,如下所示:

  17. #include <iostream>
  18. #include <string>
  19. #include <vector>
  20. #include <type_traits>
  21. int main()
  22. {
  23.   if(std::is_const<typename std::remove_reference<decltype(*begin(std::declval<std::vector<std::string>>()))>::type>::value)
  24.     std::cout<<"(a) is const\n";
  25.   if(!std::is_const<typename std::remove_reference<decltype(*std::declval<std::vector<std::string>>().begin())>::type>::value)
  26.     std::cout<<"(b) is not const\n";
  27.   if(!std::is_const<typename std::remove_reference<decltype(*begin(std::declval<std::vector<std::string>&>()))>::type>::value)
  28.     std::cout<<"(c) is not const\n";
  29.   return 0;
  30. }@H_301_3@ 
  31.  

    http://coliru.stacked-crooked.com/a/15c17b288f8d69bd

  32.  

    天真地,你不会期望(a)和(b)的不同结果当:: begin刚刚用调用vector :: begin来定义时.但是缺少std :: begin重载,它采用非const r值引用并返回迭代器(或者返回const_iteratorref-qualified vector :: begin overload)会导致这种情况发生.

解决方法

让我们一步一步地分析一下发生了什么:

>你正在调用std :: begin(std :: vector< int>&&),但是std :: begin has no overload that takes an rvalue

  1. template< class C >
  2. auto begin( C& c ) -> decltype(c.begin());
  3.  
  4. template< class C >
  5. auto begin( const C& c ) -> decltype(c.begin());@H_301_3@
  6. >由于reference collapsing,临时(xvalue)将仅绑定到const lvalue引用:

  7. If you call Fwd with an xvalue,we again get Type&& as the type of v. This will not allow you to call a function that takes a non-const lvalue,as an xvalue cannot bind to a non-const lvalue reference. It can bind to a const lvalue reference,so if Call used a const&,we could call Fwd with an xvalue.

  8. (来自链接的答案).

  9. >因此,

  10. template<class C> auto begin(const C& c) -> decltype(c.begin());@H_301_3@ 
  11.  

    正在调用overload,它返回一个const迭代器.

  12.  

    为什么?

  13.  

    因为std :: begin(v)调用v.begin(),which returns a const_iterator when called on const instances of std::vector.

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