在 C++ 中传递多个函数参数的最佳实践
Best practice for passing multiple function arguments in C++
我想知道在 C++ 中传递多个函数参数的最佳做法是什么。我想遵循 STL 中的正确通用设计原则。
我有一个通用算法函数。使用模板,它允许客户端 select 什么数据结构将用于 运行 算法以及数据将从什么容器实现中提取。但是,为了使其可重复使用,我已经 select 编辑了许多应该插入客户设计的代码的地方。
template<class CustomContainerIterator, class Queue, class Element>
void run_generic_algorithm(CustomContainerIterator container,
std::function<void(Element)> client_code1,
std::function<void(Element)> client_code2,
std::function<void(Element)> client_code3)
{
Queue queue;
//Push things iterated through onto the queue
Element queue_element = queue.top();
client_code1(queue_element);
// Run code modifying queue
client_code2(queue_element);
// Run code modifying queue
client_code3(queue_element);
}
client_code() 函数由客户端指定,可以修改客户端拥有的相同变量。在我的代码中,有 5 个客户端函数。我最初将它们全部作为 lambda 表达式传递,并捕获了我想要修改的客户端变量。但是,这会导致非常冗长的函数调用。
大多数时候我什至没有指定所有客户端函数,所以我不得不放入一个什么都不做的 lambda 函数。有没有更好的方法来实现我想要的。我想坚持正确的通用编程原则吗?
好的,我已经阅读了答案。我可以把这些想法结合起来吗?现在我觉得我不需要虚函数了。
template <typename Element>
struct Customization {
void client_code1(Element) {}
void client_code2(Element) {}
void client_code3(Element) {}
void client_code4(Foo) {}
void client_code5(Bar) {}
};
template <typename Element>
struct Implementation : public Customization {
Data some_data;
void client_code2(Element) {
//Fill some_data with information.
}
};
template<class Queue, class CustomContainerIterator, class CustomImplementation>
void run_generic_algorithm(CustomContainerIterator container,
CustomImplementation implementation)
{
Queue queue;
//Push things iterated through onto the queue
auto queue_element = queue.top();
implementation.client_code1(queue_element);
// Run code modifying queue
implementation.client_code2(queue_element);
// Run code modifying queue
implementation.client_code3(queue_element);
}
随着使用
std::vector<int> v;
Implementation <int> custom;
run_generic_algorithm<std::queue<int>>(v, custom);
在与您描述的情况类似的情况下,我已将客户端函数放入 class/struct 并将 class 作为模板参数或实例传递。 (如果函数具有来自通用函数外部的共享状态,则只需要传递一个 class 对象。)
我发现将函数放在一起 class 也可以更容易地记录函数在通用函数中负责的内容。
template< class Queue >
class a_traits{
public:
static void client_code1( Queue & );
static void client_code2();
static void client_code3();
};
template <class Container, class Queue, class Traits>
void run_generic_algorithm(const Container& container) {
Queue queue;
Traits::client_code1(queue_element);
// Run code modifying queue
Traits::client_code2();
// Run code modifying queue
Traits::client_code3();
}
there are 5 client functions.
您可以改为传递结构
template <typename Element>
struct Customization {
std::function<void(Element)> client_code1;
std::function<void(Element)> client_code2;
std::function<void(Element)> client_code3;
std::function<void(Foo)> client_code4;
std::function<void(Bar)> client_code5;
};
甚至可能是一个接口:
template <typename Element>
struct Customization {
virtual ~Customization() = default;
virtual void client_code1(Element) = 0;
virtual void client_code2(Element) = 0;
virtual void client_code3(Element) = 0;
virtual void client_code4(Foo) = 0;
virtual void client_code5(Bar) = 0;
};
然后
template<class Range, class Element>
void run_generic_algorithm(Range& r, const Customization <Element>& customization);
Most of the time I am not even specifying all the client functions, so I have to put in a lambda function that does nothing.
根据之前的评论,您可以为之前结构的成员赋予默认值。
否则您可以将默认值添加到参数或创建重载。
我想知道在 C++ 中传递多个函数参数的最佳做法是什么。我想遵循 STL 中的正确通用设计原则。
我有一个通用算法函数。使用模板,它允许客户端 select 什么数据结构将用于 运行 算法以及数据将从什么容器实现中提取。但是,为了使其可重复使用,我已经 select 编辑了许多应该插入客户设计的代码的地方。
template<class CustomContainerIterator, class Queue, class Element>
void run_generic_algorithm(CustomContainerIterator container,
std::function<void(Element)> client_code1,
std::function<void(Element)> client_code2,
std::function<void(Element)> client_code3)
{
Queue queue;
//Push things iterated through onto the queue
Element queue_element = queue.top();
client_code1(queue_element);
// Run code modifying queue
client_code2(queue_element);
// Run code modifying queue
client_code3(queue_element);
}
client_code() 函数由客户端指定,可以修改客户端拥有的相同变量。在我的代码中,有 5 个客户端函数。我最初将它们全部作为 lambda 表达式传递,并捕获了我想要修改的客户端变量。但是,这会导致非常冗长的函数调用。
大多数时候我什至没有指定所有客户端函数,所以我不得不放入一个什么都不做的 lambda 函数。有没有更好的方法来实现我想要的。我想坚持正确的通用编程原则吗?
好的,我已经阅读了答案。我可以把这些想法结合起来吗?现在我觉得我不需要虚函数了。
template <typename Element>
struct Customization {
void client_code1(Element) {}
void client_code2(Element) {}
void client_code3(Element) {}
void client_code4(Foo) {}
void client_code5(Bar) {}
};
template <typename Element>
struct Implementation : public Customization {
Data some_data;
void client_code2(Element) {
//Fill some_data with information.
}
};
template<class Queue, class CustomContainerIterator, class CustomImplementation>
void run_generic_algorithm(CustomContainerIterator container,
CustomImplementation implementation)
{
Queue queue;
//Push things iterated through onto the queue
auto queue_element = queue.top();
implementation.client_code1(queue_element);
// Run code modifying queue
implementation.client_code2(queue_element);
// Run code modifying queue
implementation.client_code3(queue_element);
}
随着使用
std::vector<int> v;
Implementation <int> custom;
run_generic_algorithm<std::queue<int>>(v, custom);
在与您描述的情况类似的情况下,我已将客户端函数放入 class/struct 并将 class 作为模板参数或实例传递。 (如果函数具有来自通用函数外部的共享状态,则只需要传递一个 class 对象。)
我发现将函数放在一起 class 也可以更容易地记录函数在通用函数中负责的内容。
template< class Queue >
class a_traits{
public:
static void client_code1( Queue & );
static void client_code2();
static void client_code3();
};
template <class Container, class Queue, class Traits>
void run_generic_algorithm(const Container& container) {
Queue queue;
Traits::client_code1(queue_element);
// Run code modifying queue
Traits::client_code2();
// Run code modifying queue
Traits::client_code3();
}
there are 5 client functions.
您可以改为传递结构
template <typename Element>
struct Customization {
std::function<void(Element)> client_code1;
std::function<void(Element)> client_code2;
std::function<void(Element)> client_code3;
std::function<void(Foo)> client_code4;
std::function<void(Bar)> client_code5;
};
甚至可能是一个接口:
template <typename Element>
struct Customization {
virtual ~Customization() = default;
virtual void client_code1(Element) = 0;
virtual void client_code2(Element) = 0;
virtual void client_code3(Element) = 0;
virtual void client_code4(Foo) = 0;
virtual void client_code5(Bar) = 0;
};
然后
template<class Range, class Element>
void run_generic_algorithm(Range& r, const Customization <Element>& customization);
Most of the time I am not even specifying all the client functions, so I have to put in a lambda function that does nothing.
根据之前的评论,您可以为之前结构的成员赋予默认值。
否则您可以将默认值添加到参数或创建重载。