boost_no_decltype_n3276.ipp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // (C) Copyright Eric Niebler 2011
  2. // Use, modification and distribution are subject to the
  3. // Boost Software License, Version 1.0. (See accompanying file
  4. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. // See http://www.boost.org/libs/config for more information.
  6. // MACRO: BOOST_NO_CXX11_DECLTYPE_N3276
  7. // TITLE: C++0x decltype v1.1 unavailable
  8. // DESCRIPTION: The compiler does not support extensions to C++0x
  9. // decltype as described in N3276 and accepted in Madrid,
  10. // March 2011:
  11. // <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3276.pdf>
  12. namespace boost_no_cxx11_decltype_n3276 {
  13. // A simplified result_of implementation.
  14. // that uses decltype.
  15. template<typename Sig>
  16. struct result_of;
  17. template<typename T>
  18. T& declvar();
  19. // use decltype
  20. template<typename Fun, typename T>
  21. struct result_of<Fun(T)>
  22. {
  23. typedef decltype(declvar<Fun>()(declvar<T>())) type;
  24. };
  25. template<typename Fun, typename T, typename U>
  26. struct result_of<Fun(T, U)>
  27. {
  28. typedef decltype(declvar<Fun>()(declvar<T>(), declvar<U>())) type;
  29. };
  30. // simple tuple type
  31. template<typename A0 = void, typename A1 = void, typename A2 = void>
  32. struct tuple;
  33. template<typename A0>
  34. struct tuple<A0, void, void>
  35. {
  36. A0 a0_;
  37. tuple(A0 const &a0)
  38. : a0_(a0)
  39. {}
  40. };
  41. template<typename A0, typename A1>
  42. struct tuple<A0, A1>
  43. {
  44. A0 a0_;
  45. A1 a1_;
  46. tuple(A0 const &a0, A1 const & a1)
  47. : a0_(a0)
  48. , a1_(a1)
  49. {}
  50. };
  51. // A node in an expression tree
  52. template<class Tag, class Args> // Args is a tuple.
  53. struct Expr;
  54. // A function object that builds expression nodes
  55. template<class Tag>
  56. struct MakeExpr
  57. {
  58. template<class T>
  59. Expr<Tag, tuple<T> > operator()(T const & t) const
  60. {
  61. return Expr<Tag, tuple<T> >(tuple<T>(t));
  62. }
  63. template<class T, typename U>
  64. Expr<Tag, tuple<T, U> > operator()(T const & t, U const & u) const
  65. {
  66. return Expr<Tag, tuple<T, U> >(tuple<T, U>(t, u));
  67. }
  68. };
  69. // Here are tag types that encode in an expression node
  70. // what operation created the node.
  71. struct Terminal;
  72. struct BinaryPlus;
  73. struct FunctionCall;
  74. typedef MakeExpr<Terminal> MakeTerminal;
  75. typedef MakeExpr<BinaryPlus> MakeBinaryPlus;
  76. typedef MakeExpr<FunctionCall> MakeFunctionCall;
  77. template<class Tag, class Args>
  78. struct Expr
  79. {
  80. Args args_;
  81. explicit Expr(Args const & t) : args_(t) {}
  82. // An overloaded operator+ that creates a binary plus node
  83. template<typename RTag, typename RArgs>
  84. typename result_of<MakeBinaryPlus(Expr, Expr<RTag, RArgs>)>::type
  85. operator+(Expr<RTag, RArgs> const &right) const
  86. {
  87. return MakeBinaryPlus()(*this, right);
  88. }
  89. // An overloaded function call operator that creates a unary
  90. // function call node
  91. typename result_of<MakeFunctionCall(Expr)>::type
  92. operator()() const
  93. {
  94. return MakeFunctionCall()(*this);
  95. }
  96. };
  97. int test()
  98. {
  99. // This is a terminal in an expression tree
  100. Expr<Terminal, tuple<int> > i = MakeTerminal()(42);
  101. i + i; // OK, this creates a binary plus node.
  102. i(); // OK, this creates a unary function-call node.
  103. // NOTE: If N3276 has not been implemented, this
  104. // line will set off an infinite cascade of template
  105. // instantiations that will run the compiler out of
  106. // memory.
  107. return 0;
  108. }
  109. }