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

时间:2015-09-29 14:03:21

标签: c++ c++11 function-pointers template-meta-programming

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

我一直在使用fredbaba的解决方案 https://stackoverflow.com/a/18422878

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

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

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

这可能吗?我可以欺骗系统并获取指向我的std :: functions的指针吗?如果你想知道为什么我需要...我采用一个包含一些C ++函数的std ::函数,在另一个函数中捕获它,然后将它存储在std :: list中。然后我创建一个指向每个列表元素的函数指针,并将它们放入我创建的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做了一些事情,但它并不重要。

这是疯了吗?我甚至可以捕获这样的函数吗?

约翰

1 个答案:

答案 0 :(得分:1)

对于类似的用例(实际上是与JNI一起使用的类工厂),我做了类似的事情。我的技术是在template struct上使用unsigned,专门化为0:每个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几乎是一个metasyntactic变量,它确保创建给定数量的特化,从而创建static函数。

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

我认为funcfoo之间的相互作用是您需要适应您的需求的。当然,每个N都是您寻找的编译时常量。