Note that there are some explanatory texts on larger screens.

plurals
  1. POUnable to pass null function-pointer as template argument
    primarykey
    data
    text
    <p>I would like to pass a function as a template argument to another function so that it can be stored and called back later. In some cases, I want to pass NULL for the call back, but I'm having trouble. Here's an example of what I'd like to be able to do:</p> <pre><code>#include &lt;iostream&gt; struct Foo { int i; }; template &lt;typename T&gt; T* T_new() { return new T(); } Foo* Foo_new() { return new Foo(); } template &lt;typename T, T* (*func)()&gt; T* T_new() { if (func) return func(); else return NULL; } int main(void) { // Works Foo* f1 = T_new&lt;Foo&gt;(); std::cout &lt;&lt; f1 &lt;&lt; std::endl; // Works Foo* f2 = T_new&lt;Foo, Foo_new&gt;(); std::cout &lt;&lt; f2 &lt;&lt; std::endl; // fails to compile, "no matching function for call to ‘T_new()’" // Foo* f3 = T_new&lt;Foo, NULL&gt;(); // std::cout &lt;&lt; f3 &lt;&lt; std::endl; return 0; } </code></pre> <p>I found <a href="https://stackoverflow.com/questions/4596499/how-to-specify-null-as-pointer-type-argument-to-template-function">this</a> similar question, but that deals with passing null as an argument to the constructor, not passing null as a template argument, and the trick there (using <code>(Foo*)0</code>) doesn't work as a template argument. </p> <p>Is there a way to work around this or do some tricky template specialisation or some other clever thing to get the desired effect?</p> <p>EDIT:</p> <p>The above was a simplified example that illustrated the problem I was having, but here's the concrete problem I'm trying to solve. I have <a href="https://bitbucket.org/alexames/luawrapper/src/37d6c4ad5886/LuaWrapper.h" rel="nofollow noreferrer">this project</a> I'm working on. This is a set of functions that make mixing C++ and Lua simpler for me (For various reasons I don't want to use LuaBind or the other existing functions I've found out there). The important function to this question is <code>luaW_register&lt;T&gt;</code>, near the bottom. This is a slightly out of date version, but it works in almost all cases. It doesn't work, however, if the constructor is private, which has just come when I tried mixing this with Box2D's <code>b2Body</code> (which needs to be made from a <code>b2World</code>). <code>luaW_defaultallocator&lt;T&gt;()</code> (and <code>luaW_defaultdeallocator&lt;T&gt;()</code>) still gets created since I'm using it as the default argument in <code>luaW_register&lt;T&gt;()</code>. </p> <p>My proposed solution was to pull the <code>allocator</code> parameter out into template parameters of <code>luaW_Register</code>. Then, if I want to use some other function to get my objects for a specific type, <code>luaW_defaultallocator</code> will not even be created. In cases like <code>b2Body</code>s, where they can't create themselves at all, I would like to be able to just pass in <code>NULL</code> as a template argument (which seems perfectly reasonable, but the compiler is choking on it for reasons that are still unclear to me, it seems like if I can set a value to <code>NULL</code> anywhere else in code I ought to be able to for templates as well). A hack I initially implemented was to pass in a boolean argument to my function which would disable the ability to call <code>Foo.new</code> from my Lua code, but that doesn't stop <code>defaultallocator</code> from compiling, and if I can use the null check in and working the way I would like it has the nice side effect of letting me simply check if there's an allocator and use that to control whether or not the <code>new</code> function gets added to the lua table.</p> <p>tl;dr: my goal was to go from this:</p> <pre><code>template &lt;typename T&gt; 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&lt;T&gt;, void (*deallocator)(T*) = luaW_defaultdeallocator&lt;T&gt;) </code></pre> <p>to this:</p> <pre><code>template &lt;typename T, T* (*allocator)() = luaW_defaultallocator&lt;T&gt;, void (*deallocator)(T*) = luaW_defaultdeallocator&lt;T&gt; &gt; void luaW_register(lua_State* L, const char* classname, const luaL_reg* table, const luaL_reg* metatable, const char** extends = NULL) </code></pre> <p>to avoid instantiation of luaW_defaultallocator in some cases, but it's looking like it might not be possible. </p> <p>The closest solution I've seen so far is to provide a function like <code>luaW_cannotalloc&lt;T&gt;(lua_State*)</code> which returns NULL and can be checked for in my luaW_register function instead of null. I suppose that would work, but it means more typing and needing to remember that function name, and NULL seems much cleaner.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload