我正在编写与库接口的C ++类。该库有许多函数,如下所示:
Library.h
int FunctionA(int deviceNumber, ...);
int FunctionB(int deviceNumber, ...);
int FunctionC(int deviceNumber, ...);
int FunctionD(int deviceNumber, ...);
int FunctionE(int deviceNumber, ...);
我的C ++类的每个实例都有一个永远不会改变的关联deviceNumber
,因此我将deviceNumber
存储为成员变量,每次调用库函数时,我都将成员传递给函数调用的第一个参数。
这很好,我没有理由改变它的方式。但出于好奇,我想知道C ++是否有任何机制来转换"允许我避免在每次调用中传递相同参数的参数。实现这一目标的显而易见的方法是超载一切。我们说我的班级叫Foo
:
Foo.cpp中
int Foo::FunctionA(...) {
// deviceNumber_ is a const member
return ::FunctionA(deviceNumber_, ...);
}
唯一的问题是这需要为每个函数调用一个方法,因此随着库的增长,如果没有代码生成器,它会变得越来越烦人。
是否有任何通用的方法来提供重载行为而不实际重载函数? C ++中是否有一种机制可以扩展"多个参数的争论?我想象它会是这样的:
// These two calls are equivalent
FunctionA(deviceNumber, ...);
FunctionA(Magic(...));
// Magic() expands the arguments, adding deviceNumber
即使解决方案比单独放置一切更加丑陋和可读性,但我很好奇是否可能。搜索后,可变参数模板似乎是最接近的匹配,但我无法真正地了解如何使用它们来实现这一目标。
答案 0 :(得分:4)
您可能对通用中继功能感到满意:
#include <iostream>
int foo1(int device_number, const char*) { std::cout << __PRETTY_FUNCTION__ << "\n"; return device_number*42; }
double foo2(int device_number) { std::cout << __PRETTY_FUNCTION__ << "\n"; return device_number*3.14159; }
struct facade {
facade(int dn) : device_number(dn) {}
template <typename F, typename... A>
auto call(F&& f, A&&... args) const {
return std::forward<F>(f)(device_number, std::forward<A>(args)...);
}
private:
int device_number;
};
int main() {
facade dev(2);
std::cout << dev.call(foo1, "yes ma'am") << "\n";
std::cout << dev.call(foo2) << "\n";
}
答案 1 :(得分:1)
我可能会选择cpp文件中的marco作为最简单的解决方案(严格来说在cpp文件中)
Variadic模板也可以提供帮助。然而,听起来你正在做一些嵌入式的东西,这可能是一个问题。
另外,我不确定您是否意味着每个FunctionA都过载或者FunctionA只涉及一个功能。
无论如何,如果有多个FunctionAs
,我的模板解决方案将会有所帮助template<typename... Args>
int Foo::FunctionA(Args&& ...args) {
return ::FunctionA(deviceNumber_, std::forward<Args>(args)...);
}
答案 2 :(得分:0)
我把伪代码用于C ++类型结构。
Class Prototype可能是以下形式。
class Foo {
private private_member_of_deviceNumber;
....
int FunctionA(...);
....
}
Foo类构造函数会将deviceNumber分配给私有成员变量。
class Foo::Foo(int deviceNumber) {
int private_member_of_deviceNumber = deviceNumber;
}
Foo类成员FunctionA(...)将喜欢这种形式。
int Foo::FunctionA(...) {
return ::FunctionA( private_member_of_deviceNumber , ...);
}
这样怎么样?