fork download
  1. #include <algorithm>
  2. #include <iostream>
  3. #include <type_traits>
  4. #include <vector>
  5. using namespace std;
  6.  
  7. // The forward_as template
  8. template<typename T, typename U>
  9. auto forward_as( U&& u ) -> typename std::conditional<
  10. std::is_reference<T>::value,
  11. typename std::remove_reference<U>::type&,
  12. typename std::remove_reference<U>::type&&>::type
  13. {
  14. return static_cast<decltype(forward_as<T, U>(u))>(u);
  15. }
  16.  
  17. // Structs for testing
  18. struct X {};
  19. struct Y {
  20. vector<X> range;
  21. Y() : range(1) {}
  22. };
  23.  
  24. // bar will tell us the actual reference type of the forwarding reference
  25. struct Bar {
  26. void operator()(X&& t) { cout << "t is a r-value reference\n"; }
  27. void operator()(X& t) { cout << "t is an l-value reference\n"; }
  28. void operator()(const X& t) { cout << "t is passed by const reference\n"; }
  29. } bar;
  30.  
  31. // Elementwise perfect forwarding of a member range
  32. template<typename T>
  33. void foo( T&& t ) {
  34. for (auto& r : t.range)
  35. bar(forward_as<T>(r));
  36. }
  37.  
  38. // Elementwise perfect forwarding of a member range
  39. template<typename T>
  40. void algo_foo( T&& t ) {
  41. std::for_each(std::begin(std::forward<T>(t).range), std::end(std::forward<T>(t).range), bar);
  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. cout << "algo_foo(Y()):\n\t";
  58. algo_foo(Y());
  59.  
  60. // Pass by l-value reference.
  61. Y y;
  62. cout << "foo(y):\n\t";
  63. foo(y);
  64. cout << "naive_foo(y):\n\t";
  65. naive_foo(y);
  66. cout << "algo_foo(y):\n\t";
  67. algo_foo(y);
  68. }
Success #stdin #stdout 0s 3472KB
stdin
Standard input is empty
stdout
foo(Y()):
	t is a r-value reference
naive_foo(Y()):
	t is an l-value reference
algo_foo(Y()):
	t is passed by const reference
foo(y):
	t is an l-value reference
naive_foo(y):
	t is an l-value reference
algo_foo(y):
	t is an l-value reference