Tested x86_64-linux, pushed to trunk.

-- >8 --

The tr1/5_numerical_facilities/random/variate_generator/37986.cc test
fails for strict -std=c++98 mode because _Adaptor(const _Engine&) is
ill-formed in C++98 when _Engine is a reference type.

Rather than attempt to make the _Adaptor handle references and pointers,
just strip references and pointers from the _Engine type before we adapt
it. That removes the need for the _Adaptor<_Engine*> partial
specialization and avoids the reference-to-reference problem for c++98
mode.

While looking into this I noticed that the TR1 spec requires the
variate_generator<E,D>::engine_value_type to be the underlying engine
type, whereas we make it the _Adaptor<E> type that wraps the engine.

libstdc++-v3/ChangeLog:

        * include/tr1/random.h (__detail::_Adaptor::_BEngine): Remove.
        (__detail::_Adaptor::_M_g): Make public.
        (__detail::_Adaptor<_Engine*, _Dist>): Remove partial
        specialization.
        (variate_generate::_Value): New helper to simplify handling of
        _Engine* and _Engine& template arguments.
        (variate_generate::engine_value_type): Define to underlying
        engine type, not adapted type.
        (variate_generate::engine()): Return underlying engine instead
        of adaptor.
        * 
testsuite/tr1/5_numerical_facilities/random/variate_generator/37986.cc:
        Fix comment.
        * 
testsuite/tr1/5_numerical_facilities/random/variate_generator/requirements/typedefs.cc:
        Check member typedefs have the correct types.
---
 libstdc++-v3/include/tr1/random.h             | 115 ++++++------------
 .../random/variate_generator/37986.cc         |   2 +-
 .../requirements/typedefs.cc                  |  51 ++++++--
 3 files changed, 84 insertions(+), 84 deletions(-)

diff --git a/libstdc++-v3/include/tr1/random.h 
b/libstdc++-v3/include/tr1/random.h
index 535f142a004..6061649c5a4 100644
--- a/libstdc++-v3/include/tr1/random.h
+++ b/libstdc++-v3/include/tr1/random.h
@@ -81,9 +81,8 @@ namespace tr1
     template<typename _Engine, typename _Distribution>
       struct _Adaptor
       { 
-       typedef typename remove_reference<_Engine>::type _BEngine;
-       typedef typename _BEngine::result_type           _Engine_result_type;
-       typedef typename _Distribution::input_type       result_type;
+       typedef typename _Engine::result_type           _Engine_result_type;
+       typedef typename _Distribution::input_type      result_type;
 
       public:
        _Adaptor(const _Engine& __g)
@@ -146,72 +145,8 @@ namespace tr1
          return __return_value;
        }
 
-      private:
        _Engine _M_g;
       };
-
-    // Specialization for _Engine*.
-    template<typename _Engine, typename _Distribution>
-      struct _Adaptor<_Engine*, _Distribution>
-      {
-       typedef typename _Engine::result_type      _Engine_result_type;
-       typedef typename _Distribution::input_type result_type;
-
-      public:
-       _Adaptor(_Engine* __g)
-       : _M_g(__g) { }
-
-       result_type
-       min() const
-       {
-         result_type __return_value;
-         if (is_integral<_Engine_result_type>::value
-             && is_integral<result_type>::value)
-           __return_value = _M_g->min();
-         else
-           __return_value = result_type(0);
-         return __return_value;
-       }
-
-       result_type
-       max() const
-       {
-         result_type __return_value;
-         if (is_integral<_Engine_result_type>::value
-             && is_integral<result_type>::value)
-           __return_value = _M_g->max();
-         else if (!is_integral<result_type>::value)
-           __return_value = result_type(1);
-         else
-           __return_value = std::numeric_limits<result_type>::max() - 1;
-         return __return_value;
-       }
-
-       result_type
-       operator()()
-       {
-         result_type __return_value;
-         if (is_integral<_Engine_result_type>::value
-             && is_integral<result_type>::value)
-           __return_value = (*_M_g)();
-         else if (!is_integral<_Engine_result_type>::value
-                  && !is_integral<result_type>::value)
-           __return_value = result_type((*_M_g)() - _M_g->min())
-             / result_type(_M_g->max() - _M_g->min());
-         else if (is_integral<_Engine_result_type>::value
-                  && !is_integral<result_type>::value)
-           __return_value = result_type((*_M_g)() - _M_g->min())
-             / result_type(_M_g->max() - _M_g->min() + result_type(1));
-         else
-           __return_value = ((((*_M_g)() - _M_g->min()) 
-                              / (_M_g->max() - _M_g->min()))
-                             * std::numeric_limits<result_type>::max());
-         return __return_value;
-       }
-
-      private:
-       _Engine* _M_g;
-      };
   } // namespace __detail
 
   /**
@@ -223,17 +158,45 @@ namespace tr1
   template<typename _Engine, typename _Dist>
     class variate_generator
     {
-      // Concept requirements.
-      __glibcxx_class_requires(_Engine, _CopyConstructibleConcept)
-      //  __glibcxx_class_requires(_Engine, _EngineConcept)
-      //  __glibcxx_class_requires(_Dist, _EngineConcept)
+      template<typename _Eng>
+       struct _Value
+       {
+         typedef _Eng type;
+
+         static const _Eng&
+         _S_ref(const _Eng& __e) { return __e; }
+       };
+
+      template<typename _Eng>
+       struct _Value<_Eng*>
+       {
+         typedef _Eng type;
+
+         __attribute__((__nonnull__))
+         static const _Eng&
+         _S_ref(const _Eng* __e) { return *__e; }
+       };
+
+      template<typename _Eng>
+       struct _Value<_Eng&>
+       {
+         typedef _Eng type;
+
+         static const _Eng&
+         _S_ref(const _Eng& __e) { return __e; }
+       };
 
     public:
       typedef _Engine                                engine_type;
-      typedef __detail::_Adaptor<_Engine, _Dist>     engine_value_type;
+      typedef typename _Value<_Engine>::type         engine_value_type;
       typedef _Dist                                  distribution_type;
       typedef typename _Dist::result_type            result_type;
 
+      // Concept requirements.
+      __glibcxx_class_requires(engine_value_type, _CopyConstructibleConcept)
+      // __glibcxx_class_requires(_Engine, _EngineConcept)
+      //  __glibcxx_class_requires(_Dist, _EngineConcept)
+
       // tr1:5.1.1 table 5.1 requirement
       typedef typename __gnu_cxx::__enable_if<
        is_arithmetic<result_type>::value, result_type>::__type _IsValidType;
@@ -246,7 +209,7 @@ namespace tr1
        * the @p _Engine or @p _Dist objects.
        */
       variate_generator(engine_type __eng, distribution_type __dist)
-      : _M_engine(__eng), _M_dist(__dist) { }
+      : _M_engine(_Value<_Engine>::_S_ref(__eng)), _M_dist(__dist) { }
 
       /**
        * Gets the next generated value on the distribution.
@@ -269,7 +232,7 @@ namespace tr1
        */
       engine_value_type&
       engine()
-      { return _M_engine; }
+      { return _M_engine._M_g; }
 
       /**
        * Gets a const reference to the underlying uniform random number
@@ -277,7 +240,7 @@ namespace tr1
        */
       const engine_value_type&
       engine() const
-      { return _M_engine; }
+      { return _M_engine._M_g; }
 
       /**
        * Gets a reference to the underlying random distribution.
@@ -308,7 +271,7 @@ namespace tr1
       { return this->distribution().max(); }
 
     private:
-      engine_value_type _M_engine;
+      __detail::_Adaptor<engine_value_type, _Dist> _M_engine;
       distribution_type _M_dist;
     };
 
diff --git 
a/libstdc++-v3/testsuite/tr1/5_numerical_facilities/random/variate_generator/37986.cc
 
b/libstdc++-v3/testsuite/tr1/5_numerical_facilities/random/variate_generator/37986.cc
index 5eeccf04771..a13094740e7 100644
--- 
a/libstdc++-v3/testsuite/tr1/5_numerical_facilities/random/variate_generator/37986.cc
+++ 
b/libstdc++-v3/testsuite/tr1/5_numerical_facilities/random/variate_generator/37986.cc
@@ -21,7 +21,7 @@
 
 #include <tr1/random>
 
-// libtsdc++/37986
+// libstdc++/37986
 void test01()
 {
   std::tr1::mt19937 mt;
diff --git 
a/libstdc++-v3/testsuite/tr1/5_numerical_facilities/random/variate_generator/requirements/typedefs.cc
 
b/libstdc++-v3/testsuite/tr1/5_numerical_facilities/random/variate_generator/requirements/typedefs.cc
index 0bdb610e31b..a71c8ddfd81 100644
--- 
a/libstdc++-v3/testsuite/tr1/5_numerical_facilities/random/variate_generator/requirements/typedefs.cc
+++ 
b/libstdc++-v3/testsuite/tr1/5_numerical_facilities/random/variate_generator/requirements/typedefs.cc
@@ -23,19 +23,56 @@
 
 #include <tr1/random>
 
+template<typename T, typename U> struct require_same; // not defined
+template<typename T> struct require_same<T, T> { };
+
+typedef std::tr1::linear_congruential<unsigned long, 16807, 0, 2147483647> E;
+typedef std::tr1::uniform_int<int> D;
+
 void
 test01()
 {
-  using namespace std::tr1;
-
-  typedef variate_generator
-    <
-    linear_congruential<unsigned long, 16807 , 0 , 2147483647>,
-    uniform_int<int>
-    > test_type;
+  typedef std::tr1::variate_generator<E, D> test_type;
 
   typedef test_type::engine_type       engine_type;
   typedef test_type::engine_value_type engine_value_type;
   typedef test_type::distribution_type distribution_type;
   typedef test_type::result_type       result_type;
+
+  require_same<engine_type, E> check_e;
+  require_same<engine_value_type, E> check_ev;
+  require_same<distribution_type, D> check_d;
+  require_same<result_type, typename D::result_type> check_r;
+}
+
+void
+test02()
+{
+  typedef std::tr1::variate_generator<E&, D> test_type;
+
+  typedef test_type::engine_type       engine_type;
+  typedef test_type::engine_value_type engine_value_type;
+  typedef test_type::distribution_type distribution_type;
+  typedef test_type::result_type       result_type;
+
+  require_same<engine_type, E&> check_e;
+  require_same<engine_value_type, E> check_ev;
+  require_same<distribution_type, D> check_d;
+  require_same<result_type, typename D::result_type> check_r;
+}
+
+void
+test03()
+{
+  typedef std::tr1::variate_generator<E*, D> test_type;
+
+  typedef test_type::engine_type       engine_type;
+  typedef test_type::engine_value_type engine_value_type;
+  typedef test_type::distribution_type distribution_type;
+  typedef test_type::result_type       result_type;
+
+  require_same<engine_type, E*> check_e;
+  require_same<engine_value_type, E> check_ev;
+  require_same<distribution_type, D> check_d;
+  require_same<result_type, typename D::result_type> check_r;
 }
-- 
2.37.3

Reply via email to