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(-)
@@ -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;
};
@@ -21,7 +21,7 @@
#include <tr1/random>
-// libtsdc++/37986
+// libstdc++/37986
void test01()
{
std::tr1::mt19937 mt;
@@ -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;
}