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<decltype(forward_as<T, U>(u))>(u);
  14. }
  15.  
  16. // Structs for testing
  17. struct X {};
  18. struct Y {
  19. vector<X> range;
  20. Y() : range(1) {}
  21. };
  22.  
  23. // bar will tell us the actual reference type of the forwarding reference
  24. template<typename T>
  25. void bar( T&& t ) {
  26. if (is_rvalue_reference<decltype(t)>::value)
  27. cout << "t is a r-value reference\n";
  28. else if (is_lvalue_reference<decltype(t)>::value)
  29. cout << "t is an l-value reference\n";
  30. else
  31. cout << "t is passed by value\n";
  32. }
  33.  
  34. // Elementwise perfect forwarding of a member range
  35. template<typename T>
  36. void foo( T&& t ) {
  37. for (auto& r : t.range)
  38. bar(forward_as<T>(r));
  39. }
  40.  
  41. // Naive and non-working attempt
  42. template<typename T>
  43. void naive_foo( T&& t ) {
  44. for (auto&& r : forward<T>(t).range)
  45. bar(r);
  46. }
  47.  
  48. int main() {
  49. // Pass by r-value reference.
  50. cout << "foo(Y()):\n\t";
  51. foo(Y());
  52. cout << "naive_foo(Y()):\n\t";
  53. naive_foo(Y());
  54.  
  55. // Pass by l-value reference.
  56. Y y;
  57. cout << "foo(y):\n\t";
  58. foo(y);
  59. cout << "naive_foo(y):\n\t";
  60. naive_foo(y);
  61. }
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