c++ - 将函数作为参数传递以避免重复代码

标签 c++ c++11 c++14 dry overloading

到目前为止,我一直在使用 C++11 编写代码,并且我正在尝试了解 auto 在较新版本中的工作原理。特别是我有两个函数(示例中的 f1 和 f2)在给定结构上工作。这两个函数几乎相同,但它们会根据操作的成员而改变,有时操作是一个值的倒数,等等......(这个例子是对真实程序的过度简化)。

我想避免使用条件和重载函数来实现此行为。您知道更清洁或更惯用的方法吗?我遗漏了这段代码中的任何问题吗?

typedef struct thing_t {
    double A;
    double B;
} THING;    

double get_A(const THING &t) {
    return t.A;
}

double get_B(const THING &t) {
    return t.B;
}

double convert(const THING &t, auto first, auto then) {
    return first(t) / then(t);
}

double f1(const THING &t) {
    return convert(t, get_A, get_B); 
}

double f2(const THING &t) {
    return convert(t, get_B, get_A);
}

int main() {
    THING t = {1.0, 2.0};
    std::cout << f1(t) << std::endl;
    std::cout << f2(t) << std::endl;
    return 0;
}

非常感谢您花时间审阅我的问题。

最佳答案

首先,您还不能使用auto 函数参数。那是非标准的 C++。此外,这个 typedef struct 是 C-ism。在 C++ 中,只需:

struct thing_t {
    double A;
    double B;
};

现在让我们谈谈概括。 convert 是否需要了解其参数?也许它本身就是一个高阶函数:

template <typename F, typename G>
auto convert(F f, G g) {
    return [=](auto const& x) { return f(x) / g(x); }
}

然后 get_Aget_B 只返回成员。我们已经有了一个语法:指向成员数据的指针(不幸的是它们不能直接调用,所以你需要 std::mem_fn ):

double f1(const thing_t& t) {
    return convert(std::mem_fn(&thing_t::A), std::mem_fn(&thing_t::B))(t);
}

C++17 引入了 std::invoke所以你可以让你的实用功能在这里更加用户友好。它可以在 C++14 中很好地实现,但它可以让你写:

template <typename F, typename G>
auto convert(F f, G g) {
    return [=](auto const& x) { return std::invoke(f, x) / std::invoke(g, x); };
}

double f1(const thing_t& t) {
    return convert(&thing_t::A, &thing_t::B)(t);
}

double f2(const thing_t& t) {
    return convert(&thing_t::B, &thing_t::A)(t);
}

你怎么看?

关于c++ - 将函数作为参数传递以避免重复代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52615112/

相关文章:

c++ - 无法使用 C++ 和 visual studio 2010 express 编译基本的 SDL 教程 - 未找到 SDL.h

c++ - 名称隐藏和访问基类的非虚函数(语法)

c++ - 候选模板被忽略 : couldn't infer template argument

C++ 11 : Calling a C++ function periodically

c++ - 编译器是否默认生成构造函数constexpr?

c++ - 在使用 auto 时初始化结构会导致 VS 2013 中的拷贝

c# - 如何找到给定数组的所有可能子集?

c++ - Boost语言环境规范化带状字符但不带重音符号

c++ - 在基于范围的 for 循环中查找具有连续内存的序列中元素的位置

c++ - 是否可以避免将参数复制到 lambda 函数?