【问题标题】:Passing integer arguments to variadic template where accepts floatings将整数参数传递给接受浮点数的可变参数模板
【发布时间】:2020-06-10 13:24:28
【问题描述】:

我正在尝试用 C++ 编写“通用 beta 函数”(https://en.wikipedia.org/wiki/Beta_function#Multivariate_beta_function)。

这是我的工作:

template <typename... Args>
constexpr auto sum(Args&&... args) {
    return (args + ...);
}

// Beta(a1, a2, ..., an) = Beta(a1, a2 + ... + an) * Beta(a2, ..., an)
template <std::floating_point F, typename... Ts>
constexpr F multivariate_beta(F a1, Ts... args) {
    static_assert(sizeof...(args) > 0);
    F value = std::beta(a1, sum(args...));
    if constexpr (sizeof...(args) == 1)
        return value;
    else
        return value * multivariate_beta(args...);
}

此函数适用于以下测试用例:

std::cout << multivariate_beta(1.0, 1.0, 1.0, 1.0) << '\n';  // should output 1 / 3!
std::cout << multivariate_beta(2.0, 3.0, 4.0) << '\n'; // should output 2! * 3! / 8!

但在以下测试用例中失败:

std::cout << multivariate_beta(1, 1, 1, 1) << '\n'; // compile error
std::cout << multivariate_beta(2, 3, 4) << '\n'; // compile error

编译器抱怨该函数只接受std::floating_point 概念类型的参数, 所以 (1, 1, 1, 1) 和 (2, 3, 4) 不是有效参数。 我对此不满意,因为 1, 1, 1, 1 和 2, 3, 4 可以隐式转换为浮点类型。

在这些情况下,如何强制将隐式转换为浮点数? 提前致谢。

【问题讨论】:

    标签: c++17 variadic-templates c++20 c++-concepts


    【解决方案1】:

    (自答) 解决方法:

    template <typename A>
    concept Arithmetic = std::is_arithmetic_v<A>;
    
    template <typename... Args>
    constexpr auto sum(Args&&... args) {
        return (args + ...);
    }
    
    // Beta(a1, a2, ..., an) = Beta(a1, a2 + ... + an) * Beta(a2, ..., an)
    template <std::floating_point F = double, Arithmetic A, typename... Ts>
    constexpr F multivariate_beta(A a1, Ts... args) {
        static_assert(sizeof...(args) > 0);
        F value = std::beta(a1, sum(args...));
        if constexpr (sizeof...(args) == 1)
            return value;
        else
            return value * multivariate_beta(args...);
    }
    

    不好的是返回值类型没有参数化,只是强制为double。正在寻找更好的解决方案...

    (编辑):解决了这个问题!是的!

    【讨论】:

    • F 始终是double
    • @PiotrSkotnicki 是的,但我认为调用 multivariate_beta&lt;float&gt;(1, 1, 1, 1) 会使 F 成为 float。调用 multivariate_beta(1, 1, 1, 1) 使 F 成为默认类型,double
    • 因为我想留下一个选项来控制返回类型。据我所知,将其设为auto 将始终强制返回类型为double,因为std::beta 的返回类型是double
    猜你喜欢
    • 2014-10-20
    • 2011-03-16
    • 2019-03-27
    • 1970-01-01
    • 1970-01-01
    • 2011-04-01
    相关资源
    最近更新 更多