【问题标题】:Unique Template Class without __LINE__ or __COUNTER__ Macros没有 __LINE__ 或 __COUNTER__ 宏的唯一模板类
【发布时间】:2015-09-29 14:03:21
【问题描述】:

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

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

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

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

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

这可能吗?我可以欺骗系统并获得指向我的 std::functions 的指针吗?如果您想知道为什么我需要... 我采用一个包装了一些 C++ 函数的 std::function,将其捕获到另一个函数中,然后将其存储在 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 做了一些事情,但这并不重要。

这很疯狂吗?我什至可以捕获这样的函数吗?

约翰

【问题讨论】:

  • 您可以使用类型而不是数字进行标记。就像Register_Function&lt;struct MyMethod_tag&gt;("MyMethod", ...); 一样,通常想出一个唯一的类型名称比使用一个唯一的编号更容易。请注意,您实际上不需要定义 MyMethod_tag - 精心制作的类型说明符兼作前向声明,这就是所需要的。
  • 这是一个有趣的解决方案,我可能会接受。这似乎有点冗长,但我想一个优点是您可以将一些信息编码到标签结构的名称中。谢谢!
  • 这是伊戈尔所说的一个例子......我想。 ideone.com/zLYETM

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


【解决方案1】:

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

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

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

【讨论】:

  • 嗯,所以当您声明 TheRegistrar 时,您硬编码了您想要的唯一模板的数量?我可以看到这个工作....我可能会选择 Igor 的答案,因为它允许我在方法标签中编码一些信息,而且它更适用于我的情况。尽管如此,我还是很想看到一个如何将其应用于多个功能的示例。我会投票给你,如果没有其他人回答,绿色复选标记就是你的!
猜你喜欢
  • 2010-10-13
  • 2013-10-22
  • 2014-06-06
  • 1970-01-01
  • 2011-07-01
  • 2018-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多