fork(1) download
  1. #include <iostream>
  2. #include <type_traits>
  3. #include <vector>
  4. using namespace std;
  5.  
  6. // The forward_as template
  7. template<typename T, typename U>
  8. auto forward_as( U&& u ) -> typename std::conditional<
  9. std::is_reference<T>::value,
  10. typename std::remove_reference<U>::type&,
  11. typename std::remove_reference<U>::type&&>::type
  12. {
  13. return static_cast<typename std::conditional<
  14. std::is_reference<T>::value,
  15. typename std::remove_reference<U>::type&,
  16. typename std::remove_reference<U>::type&&>::type>(u);
  17. }
  18.  
  19. // Structs for testing
  20. struct X {};
  21. struct Y {
  22. vector<X> range;
  23. Y() : range(1) {}
  24. };
  25.  
  26. // bar will tell us the actual reference type of the forwarding reference
  27. template<typename T>
  28. void bar( T&& t ) {
  29. if (is_rvalue_reference<decltype(t)>::value)
  30. cout << "t is a r-value reference\n";
  31. else if (is_lvalue_reference<decltype(t)>::value)
  32. cout << "t is an l-value reference\n";
  33. else
  34. cout << "t is passed by value\n";
  35. }
  36.  
  37. // Elementwise perfect forwarding of a member range
  38. template<typename T>
  39. void foo( T&& t ) {
  40. for (auto& r : t.range)
  41. bar(forward_as<T>(r));
  42. }
  43.  
  44. // Naive and non-working attempt
  45. template<typename T>
  46. void naive_foo( T&& t ) {
  47. for (auto&& r : forward<T>(t).range)
  48. bar(r);
  49. }
  50.  
  51. int main() {
  52. // Pass by r-value reference.
  53. cout << "foo(Y()):\n\t";
  54. foo(Y());
  55. cout << "naive_foo(Y()):\n\t";
  56. naive_foo(Y());
  57.  
  58. // Pass by l-value reference.
  59. Y y;
  60. cout << "foo(y):\n\t";
  61. foo(y);
  62. cout << "naive_foo(y):\n\t";
  63. naive_foo(y);
  64. }
Success #stdin #stdout 0s 3428KB
stdin
Standard input is empty
stdout
foo(Y()):
	t is a r-value reference
naive_foo(Y()):
	t is an l-value reference
foo(y):
	t is an l-value reference
naive_foo(y):
	t is an l-value reference