You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何使用std::uniform_random_bit_generator的代码编译失败?

为什么使用std::uniform_random_bit_generator概念的C++代码编译失败?

我写了一段使用std::uniform_random_bit_generator概念的C++代码,预期能正常编译,但实际编译失败。代码用的是标准库内置的随机位生成器,换成mt19937等其他生成器也会报同样的错误。我是不是错误应用了这个概念?

原代码

#include<random>
#include<print>

template<std::uniform_random_bit_generator PRNG>
void test(PRNG && rng) {
    std::uniform_int_distribution<int> dist{1, 7};
    std::print("{}\n", dist(rng));
}

int main() {
    std::minstd_rand engine{std::random_device{}()};
    test(engine);
}

编译报错信息

Clang报错:

<source>:12:5: error: no matching function for call to 'test'
   12 |     test(engine);
      |     ^~~~
<source>:5:6: note: candidate template ignored: constraints not satisfied [with PRNG = std::minstd_rand &]
    5 | void test(PRNG && rng) {
      |      ^
<source>:4:10: note: because 'std::linear_congruential_engine<unsigned long, 48271, 0, 2147483647> &' does not satisfy 'uniform_random_bit_generator'
    4 | template<std::uniform_random_bit_generator PRNG>
      |          ^
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/15.0.0/../../../../include/c++/15.0.0/bits/uniform_int_dist.h:57:4: note: because '_Gen::min()' would be invalid: type 'std::linear_congruential_engine<unsigned long, 48271, 0, 2147483647> &' cannot be used prior to '::' because it has no members
   57 |         { _Gen::min() } -> same_as<invoke_result_t<_Gen&>>;
      |           ^
1 error generated.
Compiler returned: 1

GCC 14.2报错:

<source>: In function 'int main()':
<source>:12:9: error: no matching function for call to 'test(std::minstd_rand&)'
   12 |     test(engine);
      |     ~~~~^~~~~~~~
<source>:5:6: note: candidate: 'template<class PRNG>  requires  uniform_random_bit_generator<PRNG> void test(PRNG&&)'
    5 | void test(PRNG && rng) {
      |      ^~~~
<source>:5:6: note:   template argument deduction/substitution failed:
<source>:5:6: note: constraints not satisfied
In file included from /opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/bits/random.h:35,
                 from /opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/random:48,
                 from <source>:1:
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/bits/uniform_int_dist.h: In substitution of 'template<class PRNG>  requires  uniform_random_bit_generator<PRNG> void test(PRNG&&) [with PRNG = std::linear_congruential_engine<long unsigned int, 48271, 0, 2147483647>&]':
<source>:12:9:   required from here
   12 |     test(engine);
      |     ~~~~^~~~~~~~
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/bits/uniform_int_dist.h:53:13:   required for the satisfaction of 'uniform_random_bit_generator<PRNG>' [with PRNG = std::linear_congruential_engine<long unsigned int, 48271, 0, 2147483647>&]
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/bits/uniform_int_dist.h:55:10:   in requirements  [with _Gen = std::linear_congruential_engine<long unsigned int, 48271, 0, 2147483647>&]
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/bits/uniform_int_dist.h:57:20: note: the required expression '_Gen::min()' is invalid
   57 |         { _Gen::min() } -> same_as<invoke_result_t<_Gen&>>;
      |           ~~~~~~~~~^~
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/bits/uniform_int_dist.h:58:20: note: the required expression '_Gen::max()' is invalid
   58 |         { _Gen::max() } -> same_as<invoke_result_t<_Gen&>>;
      |           ~~~~~~~~~^~
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/bits/uniform_int_dist.h:59:18: note: nested requirement 'std::bool_constant<((bool)(_Gen::min() < _Gen::max()))>::value' is not satisfied
   59 |         requires bool_constant<(_Gen::min() < _Gen::max())>::value;
      |         ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1plus: note: set '-fconcepts-diagnostics-depth=' to at least 2 for more detail
Compiler returned: 1

问题原因及解决方案

原因分析

问题出在模板参数推导和概念约束的匹配上:

  • 调用test(engine)时,engine是左值,模板参数PRNG会被推导为左值引用类型std::minstd_rand&。
  • std::uniform_random_bit_generator概念要求的是生成器类型本身(而非引用类型),因为该概念需要访问生成器的静态成员函数min()和max(),但引用类型没有静态成员,导致约束检查失败。

解决方案

有两种常用的修复方式:

方式1:移除引用折叠,改用值传递或左值引用

如果希望接受左值生成器,可以将函数参数改为普通左值引用:

template<std::uniform_random_bit_generator PRNG>
void test(PRNG & rng) { // 改为左值引用
    std::uniform_int_distribution<int> dist{1, 7};
    std::print("{}\n", dist(rng));
}

或者改用值传递(生成器通常是轻量级对象,拷贝成本低):

template<std::uniform_random_bit_generator PRNG>
void test(PRNG rng) { // 值传递
    std::uniform_int_distribution<int> dist{1, 7};
    std::print("{}\n", dist(rng));
}

方式2:使用std::remove_reference_t调整概念约束

如果想保留完美转发的参数形式,需要在概念约束中去掉引用修饰:

template<typename PRNG>
requires std::uniform_random_bit_generator<std::remove_reference_t<PRNG>>
void test(PRNG && rng) { // 保留完美转发
    std::uniform_int_distribution<int> dist{1, 7};
    std::print("{}\n", dist(rng));
}

这样无论PRNG被推导为值类型还是引用类型,std::remove_reference_t都会剥离引用,检查原始生成器类型是否满足概念。


内容的提问来源于Stack Exchange,提问作者Xirema

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 06:35:53