我有许多带有许多方法的C ++结构。 C ++结构有一个 “默认”实例,我想公开一个使用的“c”包装函数 这个默认实例。但我也想避免重复所有 prototyles。
欢迎使用C ++ 11/14/17的Alkind和/或宏技巧,但我不想使用 代码生成器。
我有一些几乎可行的东西,但我仍然在努力争取一些 的信息。
// C++ class that have a "default-instance" ///////////////////////////////////
struct Foo {
int a() { return 1; }
int b(int) { return 2; }
int c(int, int) { return 3; }
};
Foo *FOO = nullptr;
// emulating existing c code that can not be changed //////////////////////////
typedef int (*ptr_a_t)();
ptr_a_t ptr_a = nullptr;
typedef int (*ptr_b_t)(int);
ptr_b_t ptr_b = nullptr;
typedef int (*ptr_c_t)(int, int);
ptr_c_t ptr_c = nullptr;
// Wrapper code (almost generic) //////////////////////////////////////////////
template <typename T, T>
struct Proxy;
// Wrapper class that will use the defualt instance if initialized (FOO is
// hardcoded).
template <typename T, typename R, typename... Args, R (T::*mf)(Args...)>
struct Proxy<R (T::*)(Args...), mf> {
static R call(Args... args) {
if (FOO) {
// ^^^
return ((*FOO).*mf)(args...);
// HARD-CODED ^^^^
} else {
return -1;
}
}
};
// Helper function to deduce the Proxy-class (method 'b' is hardcoded)
template <typename T, typename R, typename... Args>
auto deduce_args(R (T::*mf)(Args...)) -> Proxy<R (T::*)(Args...), &T::b> {
// HARD-CODED ^
return Proxy<R (T::*)(Args...), &T::b>();
// HARD-CODED ^
}
// Wrap the methods ////////////////////////////////////////////////////////
//#define wrap_a decltype(deduce_args(&Foo::a))::call
#define wrap_b decltype(deduce_args(&Foo::b))::call
//#define wrap_c decltype(deduce_args(&Foo::c))::call
int main() {
// Test that it works
//ptr_a = &wrap_a; // does not work due to hard-coded method
ptr_b = &wrap_b;
//ptr_c = &wrap_c; // does not work due to hard-coded method
return ptr_b(0);
}
我可以使用代理中硬编码的“FOO”,因为我每个类只需要一个代理,但如果实例指针可以作为一个传递,那将会很酷 模板参数。
“deduce_args”中的硬编码方法真的很烦人,我怎么能消除 该??
有没有更好的方法(函数指针不能替换为std::function
)。
答案 0 :(得分:1)
使用C ++ 14别名被证明是一种更容易实现我想要的方式。
// compile using the "-std=c++14" flag
// C++ class that have a "default-instance" ///////////////////////////////////
struct Foo {
int a() { return 1; }
int b(int) { return 2; }
int c(int, int) { return 3; }
};
Foo *FOO = nullptr;
// emulating existing c code that can not be changed //////////////////////////
typedef int (*ptr_a_t)();
ptr_a_t ptr_a = nullptr;
typedef int (*ptr_b_t)(int);
ptr_b_t ptr_b = nullptr;
typedef int (*ptr_c_t)(int, int);
ptr_c_t ptr_c = nullptr;
// Wrapper code ///////////////////////////////////////////////////////////////
template <typename T, T, typename P, P>
struct Proxy;
template <typename T, typename R, typename... Args, R (T::*mf)(Args...),
typename P, P p>
struct Proxy<R (T::*)(Args...), mf, P, p> {
static R call(Args... args) {
if (*p) {
return ((*(*p)).*mf)(args...);
} else {
return -1;
}
}
};
// Wrap the methods ///////////////////////////////////////////////////////////
#define WRAP(n, obj, m, ptr) \
const auto &n = Proxy<decltype(&obj::m), &obj::m, obj **, &ptr>::call
WRAP(wrap_a, Foo, a, FOO);
WRAP(wrap_b, Foo, b, FOO);
WRAP(wrap_c, Foo, c, FOO);
int main() {
// Test that it works
ptr_a = &wrap_a;
ptr_b = &wrap_b;
ptr_c = &wrap_c;
return ptr_b(0);
}