jeremyong / Selene

Simple C++11 friendly header-only bindings to Lua
zlib License
810 stars 117 forks source link

fatal error: recursive template instantiation exceeded maximum depth of 256 #167

Open sebt3 opened 7 years ago

sebt3 commented 7 years ago

Hi,

This is not exactly a Selene issue but a clang one. Most complier have a max depth of 1024, but clang set this way lower. and as Selene use template extensively, the 256 limit is fast to cross :

    state["p_serv"].SetObj(*p_serv,
        "addCollector", &service::addCollector,
        "havePID",  &service::havePID,
        "getType",  &service::getType,
        "getSubType",   &service::getSubType,
        "getName",  &service::getName,
        "getID",    &service::getID,
        "setType",  &service::setType,
        "setSubType",   &service::setSubType,
        "setName",  &service::setName
    );

Trigger the error; remove a pair of argument and it compile fine.

The fix is to tell clang to behave like gcc on this with the compiler flags : "-ftemplate-depth=1024"

sebt3 commented 7 years ago

Add this to the CMakeList.txt :

if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth=1024")
endif()
adam4813 commented 7 years ago

Selene is header only, so this change would need to be added to the project that includes selene. So perhaps adding this to the README would be most prudent.

sebt3 commented 7 years ago

yet it ship with a CMakeList.txt file. This is the one that any user will have a look for his own as reference. So imho, it's the best place to document this. Well there and here in the Selene issue's lists as it's actually the 1rst place I gave a look to fix my issue :P

adam4813 commented 7 years ago

Yes it is a good place to document it here.

smt-pi commented 7 years ago

I've also run into this issue.

I would like to find a way to sequentially append functions to an object once it has already been registered within Selene, i.e. something equivalent to the following (using the original example code from above):

state["p_serv"].SetObj(*p_serv, "addCollector", &service::addCollector);
state["p_serv"].AppendObjMethod(*p_serv, "havePID", &service::havePID);
...

The library is a bit beyond my current comprehension of C++ templates though. Any pointers or suggestions would be welcome, and I will try to implement.

adam4813 commented 7 years ago

Couldn't you just assign it such as ["p_serv"]["addCollector"] = method; ? An object is just a table so to add new methods to an object you just add to its table.

At least that's my, limited, understanding.

smt-pi commented 7 years ago

Thanks for the suggestion! That won't quite compile, but using the provided operator=(function<Ret(Args...)> fun) function will. This may not be ideal for all scenarios, but in my case I'm defining special functions that I'm exposing to Lua anyway. I'm sure that other functions could be wrapped using std::function / std::bind if necessary.

So you can add as many methods as you want (well at least it compiles without increasing the stack depth now, whereas using the single function call it won't), by doing the following:

state["p_serv"].SetObj(*p_serv);
state["p_serv"]["addCollector"] = [&](float x) -> bool  {
...
};

state["p_serv"]["havePID"] = [&]() {
...
};