繁体   English   中英

如何在 c++ 模板 class 中保存用于计算的值?

[英]How to hold values used to calculations in c++ template class?

您好,我怀疑在 c++ 模板 class 中保留用于计算的值。

场景如下,我们有很多函数在计算中使用一些嵌套计算来设置一些状态/值等。这些嵌套计算对于所有这些函数都是重复的。

问题是在模板的情况下哪种方法是正确的? 将这些值保留为成员值? 或者只是调用内联 function 它将执行就地计算? 可以说该成员函数/值的值是根据模板参数及其大小计算的,并且有一些数学运算,例如乘法,减法和除法,通常说我们不想重复的困难数学公式。

具有成员值的方法:

template <typename T>
class ApproachWithMemberValue {
public:
    void firstOperation()
    {
        member_ = (member_ / importantValueUsedMultipleTime_) + something;
    }

    void secondOperation()
    {
        member_ = (1 / (member_ / importantValueUsedMultipleTime_)) * something;
    }

    //And other plenty of functions which uses importantValueUsedMultipleTime_

private:
    T val_;
    size_t member_;
    constexpr size_t importantValueUsedMultipleTime_ = resultOfOperations;
    //Some mathematical computations based on type of val_ and its value but calculated directly in importantValueUsedMultipleTime_
};

与成员 function 的方法:

template <typename T>
class ApproachWithMemberFunction {
public:
    void firstOperation()
    {
        member_ = (member_ / getImportantValueUsedMultipleTime()) + something;
    }

    void secondOperation()
    {
        member_ = (1 / (member_ / getImportantValueUsedMultipleTime())) * something;
    }

    //And other plenty of functions which uses getImportantValueUsedMultipleTime()

private:
    T val_;
    size_t member_;

    constexpr inline size_t getImportantValueUsedMultipleTime()
    {
        //Some mathematical computations based on type of val_ and its value
        return resultOfOperation;
    }
};

哪种方法在计算效率和代码质量方面更好? 调用 function getImportantValueUsedMultipleTime() 会返回计算值还是将计算放在使用它的地方?

要回答您提出的问题,似乎在没有优化的情况下,直接调用constexpr function 而不将其存储在static constexpr成员中的版本可以生成更多代码。 这种差异可能会通过优化 go 消失,但如果你想更加确定你可以声明 function consteval 查看每个版本的生成代码: https://godbolt.org/z/46xeebbcn

现在,希望能回答你想问的问题。 您需要使用某些东西初始化static constexpr成员,在您的情况下,大概是可以在编译时评估的constexpr function ,称之为getImporantValueUsedMultipleTimes() 如果此函数取决于“ val_的类型及其值”,则无法在编译时对其进行评估,因为val_是运行时变量。

您可能正在寻找的解决方案是某种类型的记忆 如果您真的希望在编译时完成计算,那么可能是这样的: https://godbolt.org/z/o7cqzjjbW

template<typename T>
consteval T computeValue(T arg) {
    return arg * 2;
};

template<typename T>
struct MemoizedValues {
    static inline const std::unordered_map<T, T> k_Values{
        {0, computeValue(0)},
        {1, computeValue(1)}};
};

template<typename T>
T getPrecomputedValue(T arg) {
    return MemoizedValues<T>::k_Values.at(arg);
};

template<typename T>
struct UsingMemoizedValues
{
    T foo() {
        return getPrecomputedValue(m_val);
    }

    T m_val;
};

int main() {
    UsingMemoizedValues<int>{}.foo();
}

但这要求您在编译时知道在运行时可能获得的所有可能的参数值(在示例中仅支持 0 和 1),这是一个很高的要求。 您更有可能需要一个系统,该系统在运行时缓存constexpr (注意,不是constevalcomputeValue()的结果,并在第二次询问时返回该结果。 如果您知道有一些常用的值,您可以使用这些值的结果初始化缓存,只要您使用文字或constexpr arguments,那么应该在编译时评估computeValue()

当然,有一些开源库可以为您执行此操作,例如https://github.com/jimporter/memo

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM