libstdc++: Fix tr1::variate_generator::engine_value_type
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.
This commit is contained in:
parent
5ad435f2a0
commit
b6adc6255f
3 changed files with 84 additions and 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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue