无法将空函数指针作为模板参数传递
Unable to pass null function-pointer as template argument
我想将一个函数作为模板参数传递给另一个函数,以便它可以存储并在以后调用。在某些情况下,我想为回调传递NULL,但我遇到了麻烦。下面是我希望能够做到的一个例子:
#include <iostream>
struct Foo {
int i;
};
template <typename T>
T* T_new() {
return new T();
}
Foo* Foo_new() {
return new Foo();
}
template <typename T, T* (*func)()>
T* T_new() {
if (func)
return func();
else
return NULL;
}
int main(void) {
// Works
Foo* f1 = T_new<Foo>();
std::cout << f1 << std::endl;
// Works
Foo* f2 = T_new<Foo, Foo_new>();
std::cout << f2 << std::endl;
// fails to compile, "no matching function for call to ‘T_new()’"
// Foo* f3 = T_new<Foo, NULL>();
// std::cout << f3 << std::endl;
return 0;
}
我发现了这个类似的问题,但是处理传递null作为构造函数的参数,而不是传递null作为模板参数,并且那里的技巧(使用(Foo*)0
)不作为模板参数工作。
是否有一种方法可以解决这个问题,或者做一些棘手的模板专门化或其他一些聪明的事情来获得所需的效果?
编辑:上面是一个简单的例子,说明了我遇到的问题,但这里是我试图解决的具体问题。我正在做一个项目。这是一组函数,使我更容易混合使用c++和Lua(出于各种原因,我不想使用LuaBind或我发现的其他现有函数)。这个问题的重要函数是luaW_register<T>
,在底部附近。这是一个有点过时的版本,但它几乎适用于所有情况。它不起作用,但是,如果构造函数是私有的,当我尝试将它与Box2D的b2Body
(需要由b2World
制成)混合时,它刚刚出现。luaW_defaultallocator<T>()
(和luaW_defaultdeallocator<T>()
)仍然得到创建,因为我使用它作为默认参数在luaW_register<T>()
。
我提出的解决方案是将allocator
参数拉到luaW_Register
的模板参数中。然后,如果我想使用其他函数来获取特定类型的对象,luaW_defaultallocator
甚至不会被创建。在像b2Body
s这样的情况下,他们根本无法创建自己,我希望能够将NULL
作为模板参数传递(这似乎是完全合理的,但是编译器因为我仍然不清楚的原因而窒息,似乎如果我可以在代码中的其他任何地方设置NULL
的值,我应该也能够为模板设置)。黑客我最初实现是通过在一个布尔参数函数将禁用调用Foo.new
从Lua代码的能力,但这并不阻止defaultallocator
编译,如果我可以使用null检查和工作方式我想它有不错的副作用让我简单地检查是否有一个分配器和用它来控制是否new
函数添加到Lua表。
tl;dr:我的目标是从这里开始:
template <typename T>
void luaW_register(lua_State* L, const char* classname, const luaL_reg* table, const luaL_reg* metatable, const char** extends = NULL, bool disablenew = false, T* (*allocator)() = luaW_defaultallocator<T>, void (*deallocator)(T*) = luaW_defaultdeallocator<T>)
:
template <typename T, T* (*allocator)() = luaW_defaultallocator<T>, void (*deallocator)(T*) = luaW_defaultdeallocator<T> >
void luaW_register(lua_State* L, const char* classname, const luaL_reg* table, const luaL_reg* metatable, const char** extends = NULL)
以避免在某些情况下实例化luaW_defaultallocator,但看起来这可能不可能。
到目前为止,我所见过的最接近的解决方案是提供一个像luaW_cannotalloc<T>(lua_State*)
这样的函数,它返回NULL,可以在我的luaW_register函数中检查,而不是NULL。我想这可以工作,但这意味着更多的输入和需要记住函数名,NULL似乎更干净。
这可以通过使用模板重载来解决。而不是只有一个' T_new '签名,你将有一个签名用于NULL情况,一个用于其他情况:
// Unused signature, no implementation so using this will result in link error
template<typename T, typename F>
T* T_new();
// NULL overload (NULL is an int)
template<typename T, int func>
T* T_new()
{
assert(func == 0 && "Signature should only be used with NULL");
return NULL;
}
// Valid function pointer overload
template<typename T, T* (*func)()>
T* T_new()
{
// I don´t think it´s possible with NULL functions now, but if it is
// we'll handle that too
if (func)
return func();
return NULL;
}
技巧在于认识到NULL实际上是一个int,并使用它来处理不同重载中的NULL情况。
空指针的问题是模板指针实参必须具有外部链接。null没有链接
如何让事情工作:不管你想要达到什么目的,似乎你选择了错误的工具。
干杯,hth。
你可以(我认为)设置一个适当类型的常量并使用它:
(Foo*)(*make_null_foo)() = 0;
Foo* f3 = T_new<Foo, make_null_foo>();
或者在c++ 0x中,您应该能够使用新的nullptr
关键字。
或者您可以按照注释所建议的那样做,并通过创建一个返回null的实际函数来简化逻辑,而不是为空函数指针进行特殊的大小写:
Foo* make_null_foo() { return 0; }
Foo* f3 = T_new<Foo, make_null_foo>();
。
看起来很丑,但是很好用:
Foo* f3 = T_new<Foo, (Foo* (*)())NULL>();
我真的不认为模板在这里有意义,我不确定你是否真的想过这个…为什么你要静态地调用一个函数,知道它将返回NULL?
无论如何,你可以这样做:
template <typename T, T* (*func)()>
T* T_new() {
return func();
}
template <typename T>
T* T_new() {
return NULL;
}
或者如果您需要通过中间模板(例如,您可能不知道在给定的点上函数是否将null,您可以遵循null对象模式并提供null函数:
template <typename T>
T* null_new() { return 0; }
template <typename T, T* (*f)() >
T* T_new() {
return f();
}
// user code:
X* p = T_new<X, null_new >();
或者,忘记使用函数指针作为模板的实参,而将其作为实参传递给函数:
template <typename T>
T* T_new( T* (*func)() = 0 ) {
if (func)
return func();
else
return NULL;
}
- 使用指向成员的指针将成员函数作为参数传递
- 修改函数中的指针(将另一个指针作为参数传递)
- 将成员函数指针作为参数传递给模板方法
- 使用引用与指针将数组作为参数传递
- 如何将成员函数作为回调参数传递给需要"typedef-ed"自由函数指针的函数?
- 如何在不使用指针的情况下将派生类的对象作为参数传递给基类中的函数?
- 将函数指针数组中的函数指针作为模板参数传递
- 无法将指向类的成员函数的函数指针作为参数传递给同一类的另一个成员函数
- 如何将指针变量作为引用参数传递?
- 如何将子类作为函数的参数传递给期望基类,然后将该对象传递到指向这些抽象类对象的指针向量中?
- Qt5 - 如何将"QList<T> *"指针作为信号参数传递,并在完成后将其删除?
- C++将指向成员的指针作为模板参数传递
- 通过引用函数传递指针参数是什么意思?
- C++ 将派生类的成员函数指针作为参数传递时选择了错误的模板专用化
- 将函数指针作为函数参数传递的目的
- 将派生类作为参数传递给方法,该方法是具有智能指针的基类
- 使用 C++11 将指向成员函数的指针作为参数传递
- 如何在程序集函数中将元素数组作为参数传递时转发 ARM 寄存器的地址指针
- 在一行中将默认类型值上的指针作为参数传递
- 将双指针作为参数传递给需要引用 std::vector <double>的函数