没有__LINE__或__COUNTER__宏的唯一模板类

Unique Template Class without __LINE__ or __COUNTER__ Macros

本文关键字:唯一 LINE COUNTER 没有      更新时间:2023-10-16

首先,让我从我要做的事情开始。我正在开发一个库,它使在c++代码中嵌入Python解释器更容易一些,而且我想利用一些c++ 11的特性。我大量使用std::函数,这是一个问题,因为Python大量使用经典函数指针。

我一直在使用弗雷德巴巴在https://stackoverflow.com/a/18422878

这可能不是一个好主意,但推理似乎是合理的;对于每个std::函数,您都需要一个指针,您需要创建一些类或结构,其中包含调用感兴趣的std::函数的静态函数,并且任何类函数指针都可以指向静态函数。

然而,这意味着你必须确保创建的每个结构都是唯一的;该线程中的海报使用唯一整数作为标识符,这很麻烦。在我的代码中,我使用LINE宏(COUNTER似乎从来没有工作过),但这当然迫使我将所有内容放在一个文件中,以避免行号冲突。

我发现有人问过类似的问题,但没有人真的这么做;为了实现这一点,标识符必须是编译时常数,我发现的许多解决方案在这方面都失败了。

这可能吗?我可以欺骗系统并获得指向我的std::函数的指针吗?如果你想知道我为什么要…我取一个std::函数来包装某个c++函数,将其捕获到另一个函数中,然后将其存储在std::列表中。然后,我创建一个指向每个列表元素的函数指针,并将它们放在我创建的Python模块中。

// Store these where references are safe
using PyFunc = std::function<PyObject *(PyObject *, PyObject *)>;
std::list<PyFunc> lst_ExposedFuncs;
...
// Expose some R fn(Args...){ ... return R(); }
template <size_t idx, typename R, typename ... Args>
static void Register_Function(std::string methodName, std::function<R(Args...)> fn, std::string docs = "")
{
    // Capture the function you'd like to expose in a PyFunc
    PyFunc pFn = [fn](PyObject * s, PyObject * a)
    {
        // Convert the arguments to a std::tuple
        std::tuple<Args...> tup;
        convert(a, tup);
        // Invoke the function with a tuple
        R rVal = call<R>(fn, tup);
        // Convert rVal to some PyObject and return
        return alloc_pyobject(rVal);
    };
    // Use the unique idx here, where I'll need the function pointer
    lst_ExposedFunctions.push_back(pFn);
    PyCFunction fnPtr = get_fn_ptr<idx>(lst_ExposedFunctions.back());
}

从那里开始,我实际上用fnPtr做了一些事情,但这并不重要。

这很疯狂吗?我能捕捉到这样一个函数吗?

约翰

对于一个类似的用例(实际上是一个与JNI一起使用的类工厂),我做了一些模糊类似的事情。我的技术是在unsigned上使用专门化为0的template struct:每个struct包含一个函数-您可以将其适应为指针有效的static成员。我还展示了如何使用依赖于特定专门化的参数调用函数foo(不确定您是否需要这个,但以防万一)。

extern bar* foo(const unsigned& id); // The function that gets called
template<unsigned N> struct Registrar
{
    static bar* func()
    {
        return foo(N - 1);
    }
private:
    Registrar<N - 1> m_next; // Instantiate the next one.
};
template<> struct Registrar<0> // To block the recursion
{
};
namespace
{
    Registrar</*ToDo - total number here*/> TheRegistrar;
}

TheRegistrar基本上是一个元异步变量,它确保了给定数量的特化,因此创建了static函数。

(由于各种技术原因,我不得不以相反的顺序实例化我的模板:如果你不需要,那么你可以相应地调整。)

我想这是funcfoo之间的相互作用,你需要适应你的需求。当然,每个N都是您所查找的编译时常量。