random_device
, no string
s attached
1. Introduction and motivation
2. Proposed wording for C++20
29.6.6 Class random_device [rand.device]
3. References
[rand.device] /3 defines the constructor of std::random_device
as follows [N4659].
This wording apparently has not been touched since the original proposal in 2002 [N1398].
explicit random_device(const string& token = implementation-defined);
Effects: Constructs a
random_device
nondeterministic uniform random bit generator object. The semantics and default value of thetoken
parameter are implementation-defined.(Footnote: The parameter is intended to allow an implementation to differentiate between different sources of randomness.)
On libc++, the default and only supported value of this parameter is the 12-character string
"/dev/urandom"
.
On libstdc++, the supported values include "/dev/urandom"
, "/dev/random"
,
"default"
, "mt19937"
, and anything that looks like an input to strtoul
;
the default value changes depending on user-controllable preprocessor macros.
Notice that there is no way to construct an object of type std::random_device
without first constructing an object of type std::string
. This may be problematic
for codebases where using the heap is forbidden.
Furthermore, std::random_device
's constructor is not allocator-aware;
it requires that the input string be constructed using std::allocator
.
This requires linking in (and template-instantiating) all of the machinery of
std::allocator
, including operator new
, even in programs that
just want the default behavior of std::random_device
. This machinery will be
instantiated, compiled, and linked in, even if the implementation-defined default value
is subject to Small String Optimization!
There are many possible overload sets which would adequately address my concern here:
()
and (const string&)
— my proposed solution()
and (string_view)
(string_view = default)
(const string&)
and (string_view = default)
()
and (const string&)
and (string_view)
string_view
. Solutions 4 and 5 introduce
the possibility of overload resolution ambiguity in the case of random_device(X())
where X()
is implicitly convertible to either string
or string_view
.
Any solution involving string_view
has the pitfall that a user-provided
string_view
is not necessarily null-terminated; so if the constructor wants to
pass it to fopen
(for example), it will have to copy the user-provided bytes into
a null-terminated array (perhaps allocated, perhaps of size PATH_MAX
/MAX_PATH
on the stack). It is better to use the user-provided buffer directly.
The wording in this section is relative to WG21 draft N4659 [N4659], that is, the current draft of the C++17 standard.
Edit paragraphs 2 and 3 as follows.
class random_device {
public:
// types
using result_type = unsigned int;
// generator characteristics
static constexpr result_type min() { return numeric_limits<result_type>::min(); }
static constexpr result_type max() { return numeric_limits<result_type>::max(); }
// constructors
random_device();
explicit random_device(const string& token= implementation-defined);
// generating functions
result_type operator()();
// property functions
double entropy() const noexcept;
// no copy functions
random_device(const random_device&) = delete;
void operator=(const random_device&) = delete;
};
random_device();
explicit random_device(const string& token= implementation-defined);
Effects: Constructs a
random_device
nondeterministic uniform random bit generator object. The semanticsand default valueof thetoken
parameter are implementation-defined.(Footnote: The parameter is intended to allow an implementation to differentiate between different sources of randomness.)