gpt4 book ai didi

c++ - 将可变参数模板转换为 constexpr

转载 作者:行者123 更新时间:2023-11-30 05:17:06 25 4
gpt4 key购买 nike

我想知道是否可以使用更简单的代码将通过参数包调用的简单循环转换为 constexpr。此示例代码演示了我正在尝试做什么

struct Student {
AgeCategory age;
Income income;
bool is_student;
CreditRating credit_rating;
bool buys_computer;
};

auto find_probability(const double x, const double mean, const double stdev) -> double;

typedef std::tuple<double, double> MeanStdDev;
typedef std::vector<MeanStdDev> MeanStdDevVec;


// This code seems verbose to me. Is there a simpler way to express this
// loop which iterates over a vector and parameter pack, possibly
// using constexpr. C++14/17 idioms are fine.
template<typename Attr>
auto get_probability(const MeanStdDevVec& v, const size_t n, const Student& s, Attr attr) -> double {
double mean, stdev;
std::tie(mean, stdev) = v[n];

return find_probability(static_cast<double>(std::invoke(attr, s)), mean, stdev);
}

template<typename First, typename... Attr>
auto get_probability(const MeanStdDevVec& v, const size_t n, const Student& s, First f, Attr... attr) -> double {
double mean, stdev;
std::tie(mean, stdev) = v[n];

return find_probability(static_cast<double>(std::invoke(f,s)), mean, stdev) * get_probability(v, n + 1, s, attr...);
}

template<typename ...Attr>
auto calculate_class_probability(const std::map<bool, MeanStdDevVec>& summaries, const Student& s, Attr... attributes) {
for (const auto& i : summaries) {
get_probability(i.second, 0L, s, attributes...);
}
}

调用自

 Student s;
calculate_class_probability(class_summaries, s , &Student::age, &Student::income, &Student::credit_rating, &Student::is_student);

最佳答案

它不一定会使代码整体更短,但它确实分离出了一个通用部分,您可以轻松地重用它,恕我直言,它使代码更清晰。在这种特殊情况下,关键是将包映射到特定类型数组的函数:

template <class T, class F, class ... Args>
std::array<T, sizeof...(Args)> pack_to_array(F f, Args&& ... args) {
return {(f(std::forward<Args>(args)))...};
}

在您的情况下,这还不够,因为您想用 vector 压缩它。因此,对此的一个有用的修改是使 pack 元素的整数索引可用并将其传递给函数:

template <class T, class F, class ... Args>
std::array<T, sizeof...(Args)> index_pack_to_array(F f, Args&& ... args) {
std::size_t i = 0;
return {(f(i++, std::forward<Args>(args)))...};
}

现在,您可以像这样使用这个函数:

template<typename... Attr>
double get_probability(const MeanStdDevVec& v, const Student& s, Attr... attr) {

assert(v.size() == sizeof...(Attr));
auto probs = index_pack_to_array<double>(
[&] (std::size_t i, auto&& a) -> double {
return // ... (get probability from v[i], s, and a)
},
std::forward<Attr>(attr)...);

return std::accumulate(probs.begin(), probs.end(), 1.0,
[] (double p1, double p2) { return p1 * p2; });
}

关于c++ - 将可变参数模板转换为 constexpr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42281018/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com