没有 __LINE__ 或 __COUNTER__ 宏的唯一模板 Class
Unique Template Class without __LINE__ or __COUNTER__ Macros
首先,让我从我正在尝试做的事情开始。我正在开发一个库,可以更轻松地在 C++ 代码中嵌入 Python 解释器,并且我想利用一些 C++11 功能。我大量使用 std::functions,这是一个问题,因为 Python 大量使用 classic 函数指针。
我一直在使用 fredbaba 的解决方案
这可能不是一个好主意,但推理似乎是合理的;对于每个 std::function 你也想要一个指针,你需要创建一些 class 或带有调用感兴趣的 std::function 和任何 class 函数的静态函数的结构指针可以指向静态函数。
但是,这意味着您必须确保创建的每个结构都是唯一的;该线程的发帖者使用唯一的整数作为标识符,这很麻烦。在我的代码中,我使用了 LINE 宏(COUNTER 似乎从来没有起作用),但是那当然迫使我将所有内容放在一个文件中以避免行号冲突。
我发现有人问过类似的问题,但 none 他们确实做到了;为了让它起作用,标识符必须是一个编译时间常量,我发现的许多解决方案在这方面都失败了。
这可能吗?我可以欺骗系统并获得指向我的 std::functions 的指针吗?如果您想知道为什么我需要...我采用了一个 std::function 来包装一些 C++ 函数,将其捕获在另一个函数中,然后将其存储在 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 做了一些事情,但这并不重要。
这是疯了吗?我什至可以捕获这样的函数吗?
约翰
我为类似的用例做了一些大致相似的事情(实际上是一个 class 用于 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
函数。
(由于各种技术原因,我必须以相反的顺序实例化我的模板:如果您不需要,可以相应地进行调整。)
我想这是 func
和 foo
之间的相互作用,您需要根据自己的需要进行调整。当然,每个 N
都是您要查找的 编译时 常量。
首先,让我从我正在尝试做的事情开始。我正在开发一个库,可以更轻松地在 C++ 代码中嵌入 Python 解释器,并且我想利用一些 C++11 功能。我大量使用 std::functions,这是一个问题,因为 Python 大量使用 classic 函数指针。
我一直在使用 fredbaba 的解决方案
这可能不是一个好主意,但推理似乎是合理的;对于每个 std::function 你也想要一个指针,你需要创建一些 class 或带有调用感兴趣的 std::function 和任何 class 函数的静态函数的结构指针可以指向静态函数。
但是,这意味着您必须确保创建的每个结构都是唯一的;该线程的发帖者使用唯一的整数作为标识符,这很麻烦。在我的代码中,我使用了 LINE 宏(COUNTER 似乎从来没有起作用),但是那当然迫使我将所有内容放在一个文件中以避免行号冲突。
我发现有人问过类似的问题,但 none 他们确实做到了;为了让它起作用,标识符必须是一个编译时间常量,我发现的许多解决方案在这方面都失败了。
这可能吗?我可以欺骗系统并获得指向我的 std::functions 的指针吗?如果您想知道为什么我需要...我采用了一个 std::function 来包装一些 C++ 函数,将其捕获在另一个函数中,然后将其存储在 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 做了一些事情,但这并不重要。
这是疯了吗?我什至可以捕获这样的函数吗?
约翰
我为类似的用例做了一些大致相似的事情(实际上是一个 class 用于 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
函数。
(由于各种技术原因,我必须以相反的顺序实例化我的模板:如果您不需要,可以相应地进行调整。)
我想这是 func
和 foo
之间的相互作用,您需要根据自己的需要进行调整。当然,每个 N
都是您要查找的 编译时 常量。