模板参数与声明不兼容

Rai*_*dex 2 c++ c++-concepts c++20

我有一个函数应该生成随机整数或随机浮点值。为此我想使用概念。

由于整数和浮点数分别需要不同的分布,因此std::uniform_int_distributionstd::uniform_real_distribution使用单独的结构来选择正确的类型 - 也具有概念重载。“选择器”看起来像这样:

template<std::integral I>
struct distribution_selector {
    using type = std::uniform_int_distribution<I>;
};

template<std::floating_point F>
struct distribution_selector {
    using type = std::uniform_real_distribution<F>;
};
Run Code Online (Sandbox Code Playgroud)

您会看到,我过去using常常选择不同的类型,具体取决于我使用的是整数类型还是浮点类型。

现在我的实际功能:

template<typename T = float, random_mode quality = random_mode::high_quality>
requires std::integral<T> || std::floating_point<T>
constexpr inline T rand(random& r, T min = std::numeric_limits<T>::min(), T max = std::numeric_limits<T>::max()) {
    using distribution = distribution_selector<T>::type;
    if constexpr(quality == random_mode::low_quality) {
        return distribution<T>(min, max)(r.low_quality_engine);
    } else {
        return distribution<T>(min, max)(r.high_quality_engine);
    }
}
Run Code Online (Sandbox Code Playgroud)

演示

我收到以下错误 (msvc):

Error (active)  E3244   template constraint not satisfied   Runtime C:\...\rand.h   35      type constraint failed for "float"
atomic constraint evaluates to false
          detected during instantiation of "T raid::rand(raid::random &r, T min = std::numeric_limits<T>::min(), T max = std::numeric_limits<T>::max()) [with T=float, quality=raid::random_mode::low_quality]" at line 34
Run Code Online (Sandbox Code Playgroud)
Error (active)  E0519   type "distribution" may not have a template argument list   Runtime C:\...\rand.h   37      detected during instantiation of "T raid::rand(raid::random &r, T min = std::numeric_limits<T>::min(), T max = std::numeric_limits<T>::max()) [with T=float, quality=raid::random_mode::low_quality]" at line 34
Run Code Online (Sandbox Code Playgroud)

我缺少什么?

Nim*_*rod 6

在专业化中使用这些概念,但不要在主模板的声明中使用这些概念。另外,distribution它不是模板,它的类型是根据其上下文确定的。

template <typename T>
struct distribution_selector;

template<std::integral I>
struct distribution_selector<I> {
    using type = std::uniform_int_distribution<I>;
};

template<std::floating_point F>
struct distribution_selector<F> {
    using type = std::uniform_real_distribution<F>;
};

template<typename T = float, random_mode quality = random_mode::high_quality>
requires std::integral<T> || std::floating_point<T>
constexpr inline T rand(random& r, T min = std::numeric_limits<T>::min(), T max = std::numeric_limits<T>::max()) {
    using distribution = distribution_selector<T>::type;
    if constexpr(quality == random_mode::low_quality) {
        return distribution(min, max)(r.low_quality_engine);
    } else {
        return distribution(min, max)(r.high_quality_engine);
    }
}

Run Code Online (Sandbox Code Playgroud)

演示