如何简化多个逻辑相同但参数类型不同的函数?

问题描述 投票:0回答:3
void functionA(A a){
  for(auto x: vector_of_x) {
    // duplicate code, which cannot be moved to a common function
    x.abc(a);
    // some more duplicate code, which cannot be moved to a common function
  }
}

void functionB(B b){
  for(auto x: vector_of_x) {
    // duplicate code, which cannot be moved to a common function
    x.def(b);
    // some more duplicate code, which cannot be moved to a common function
  }
}

functionA 和 functionB 中的重复代码相当多,所以我希望删除重复代码。实现这一目标的最佳方法是什么?

c++
3个回答
2
投票

您可以将

functionA
functionB
合并到函数模板中,可以在其中自定义是否调用
abc
def

template <auto MemberFunction, typename T>
void function(T t){
  for(auto x: vector_of_x) {
    // duplicate code, which cannot be moved to a common function
    (x.*MemberFunction)(t);
    // some more duplicate code, which cannot be moved to a common function
  }
}

void functionA(A a){
  function<&A::abc>(a);
}

void functionB(B b){
  function<&B::def>(b);
}

但是,成员函数指针在语法上有点棘手,而且不太灵活。 例如,如果您还想调试打印某些内容而不是仅仅调用

A::abc
,该怎么办? 因此,在大多数情况下,您将使用 lambda 表达式(或任何其他可调用对象):

template <typename F>
void function(F f){
  for(auto x: vector_of_x) {
    // duplicate code, which cannot be moved to a common function
    std::invoke(f, x); // or x(f), if that's sufficient
    // some more duplicate code, which cannot be moved to a common function
  }
}

void functionA(A a){
  function( [&a](X& x) { x.abc(a); } );
}

void functionB(B b){
  function( [&b](X& x) { x.def(b); } );
}

后一种解决方案非常惯用;这也是标准库中的

std::for_each
等算法所做的事情。


2
投票

正如 Raymond Chan 在评论中指出的,提供 lambda 作为参数将提供一种解决方案。例如

#include <iostream>
#include <functional>

struct A {
    void abc() const { std::cout << "A::abc\n"; }
};

struct B {
    void def() const { std::cout << "B::def\n"; }
};

template <typename T>
void foo(T x, std::function<void(T)> f) {
    f(x);
}

int main() {
    A a;
    B b;

    foo<A&>(a, [&a](const auto x) { x.abc(a); });
    foo<B&>(b, [&b](const auto x) { x.def(b); });
}

输出:

A::abc
B::def

-1
投票

如果你想对两种类型做不同的事情,那就应该敲响警钟:函数重载。您可以这样做,而不是调用成员函数

void do_something(const auto& x,A& a) { x.abc(a); }
void do_something(const auto& x,B& b) { x.def(b); }

这给我们留下了两个函数,

functionA
functionB
,它们与模一类型相同,并且敲响了下一个铃声:函数模板。

template <typename T>
void functionA(T a){
  for(auto x: vector_of_x) {
    // code that is now in a common function 
    do_something(x,a);
    // more code, that is now in a common function
  }
}

如果您有更多类型需要

do_something
,您可以编写更多重载。或者您可以考虑编写一个特征,根据
T
选择要调用的成员。

© www.soinside.com 2019 - 2024. All rights reserved.