c++11 - 使用默认实例为 c++ 对象创建 c-wrappers 并推导原型(prototype)

标签 c++11 templates c++14 template-meta-programming

我有许多 C++ 结构和许多方法。 C++ 结构有一个 “默认”实例,我想公开一个使用的“c”包装函数 这个默认实例。但我也想避免重复所有 原型(prototype)。

欢迎使用 C++11/14/17 和/或宏技巧,但我不想使用 代码生成器。

我有一些几乎可以工作的东西,但我仍在努力解决一些问题 详情。

// 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代替)。

最佳答案

事实证明,使用 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);
}

关于c++11 - 使用默认实例为 c++ 对象创建 c-wrappers 并推导原型(prototype),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40843774/

相关文章:

c++ - std::shared_ptr 类工厂 C++

c++ - 了解 Windows 中代码块的 g++ 版本

php - 如何在PHP Plates模板引擎上显示错误

c++ - 我在构建 C++ 堆栈模板方面需要帮助。 "StackType<int>::~StackType<int>(void)"错误?

c++ - 霍夫曼压缩器/解压器

c++ - 局部自动函数变量的销毁与返回值的构造之间的顺序

c++ - 重载、可变参数函数和 bool 类型

c++ - 如何获得 std::regex 的所有可能匹配项

c++ - 具有通用引用的成员函数模板不接受左值

c++ - 使 Qt5 应用程序的第二个实例将命令行参数传输到第一个实例