c++ - 成员属性的 std::function 模板参数推导

标签 c++ templates c++14

通过这个小例子,我试图让编译器自动推导出第二个参数的模板实参。这可行,但没有我想要的那么简洁。

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


// This works  (A)
template<typename R>
auto calc_mean(const std::vector<Student> & in, std::function<R (Student const&)> attr)-> double
{
    const auto mean = std::accumulate(std::begin(in), std::end(in), 0.0, [&attr](auto acc, const auto& val) {
        // Call the attribute passed in
        return acc += static_cast<double>(attr(val));
    }) / static_cast<double>(in.size());
    return mean;
}

// This doesn't work (B)
template<typename T>
auto calc_mean(const std::vector<Student> & in, T attr)-> double
{
    const auto mean = std::accumulate(std::begin(in), std::end(in), 0.0, [&attr](auto acc, const auto& val) {
    // Call the attribute passed in
    return acc += static_cast<double>(attr(val));
}) / static_cast<double>(in.size());
  return mean;
}

// Caller (A) - works but I have to explicitly state the attribute type
mean_stddev<AgeCategory>(buy, &Student::age);
// Caller (B) - what I'd like to be able to do and let compiler infer types
mean_stddev(buy, &Student::age);

错误是

>..\src\Main.cpp(16): error C2672: mean_stddev': no matching overloaded function found
1>..\src\Main.cpp(16): error C2784: 'std::tuple<double,double> mean_stddev(const std::vector<Student,std::allocator<_Ty>> &,T *)': could not deduce template argument for 'T *' from AgeCategory Student::* '
1>          with
1>          [
1>              _Ty=Student
1>          ]
1>  c:\users\chowron\documents\development\projects\ml\src\Bayes.h(25): note: see declaration of mean_stddev'

我必须对 B 的函数声明做些什么才能使用更简洁的语法。

最佳答案

要调用attr,您需要使用std::invoke :

template <class R> // <-- NB: R, not T
double calc_mean(const std::vector<Student>& in, R attr)
{
    const auto mean = std::accumulate(in.begin(), in.end(), 0.0, [&attr](auto acc, const auto& val) {
        return acc + static_cast<double>(std::invoke(attr, val));
    }) / static_cast<double>(in.size());
    return mean;
}

或者老实说:

template <class R> // <-- NB: R, not T
double calc_mean(const std::vector<Student>& in, R attr)
{
    double sum = 0.0;
    for (auto const& s : in) {
        sum += std::invoke(attr, s);
    }
    return sum / in.size();
}

invoke() 是一个 C++17 函数模板,但您可以根据所附引用在 C++11 中实现它。它将为函数、函数对象和指向成员的指针做正确的事情——这基本上就是你想要的。

关于c++ - 成员属性的 std::function 模板参数推导,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42230529/

相关文章:

c++ - 在其他窗口中使用 QApplication::activeWindow->winId() 时,QT 5.5 程序崩溃

c++ - 类型转换指针构造函数调用

c++ - 这个 std::decay 的实现是正确的吗

c++ - qtcreator中C++14的编译

c++ - 使用 gnu coreutils 在 C++ 中查找 include guard 拼写错误

C++11 CMake : Regex fails

c++ - 不定义函数的基本模板案例是常见的做法吗?

c++ - 用模板实现虚函数的覆盖机制

c++ - 如何定义和使用指向 "array"成员的指针?

c++ - 操作原始内存的正确数据类型