Unique Template Class without __LINE__ or __COUNTER__ Macros
Question: First, let me start with what I'm trying to do. I'm working on a library that
makes embedding a Python interpreter in C++ code a bit easier, and I'd like to
leverage some C++11 features. I'm using std::functions quite heavily, which is
a problem since Python makes heavy use of classic function pointers.

I've been using fredbaba's solution found at
<http://stackoverflow.com/a/18422878>

which may not be a good idea, but the reasoning seems sound; for every
std::function you'd like a pointer too, you need to create some class or
struct with a static function that invokes the std::function of interest, and
any class function pointers can point to the static function.

However, that means you've got to ensure every struct created is unique; the
poster from that thread uses a unique integer as an identifier, which is
cumbersome. In my code I use the LINE macro (COUNTER never seems to work), but
that of courses forces me to put everything in one file to avoid line number
conflicts.

I've found similar questions asked but none of them really do it; in order for
this to work the identifier has to be a compile time constant, and many of the
solutions I've found fail in this regard.

Is this possible? Can I cheat the system and get pointers to my
std::functions? If you're wondering why I need to... I take a std::function
that wraps some C++ function, capture it in yet another function, then store
that in a std::list. Then I create a function pointer to each list element and
put them in a Python Module I create.

    
    
    // 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());
    }
    

From there on I actually do something with fnPtr, but it's not important.

Is this crazy? Can I even capture a function like that?

John


Answer: I do something vaguely similar for a similar use case (actually a class
factory for use with a JNI). My technique is to use a `template struct` on an
`unsigned` with a specialisation for 0: Each `struct` contains a function -
you could adapt this to a `static` member for which a pointer would be valid.
I also show how you could call a function `foo` with a parameter dependent on
a particular specialisation (not sure you need this, but included just in
case).

    
    
    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` is pretty much a metasyntactic variable which ensures that a
given number of specialisations, and hence `static` functions are created.

(For various technical reasons I have to instantiate my templates in reverse
order: if you don't need that then you can adjust accordingly.)

I imagine it's the interplay between `func` and `foo` that you'll need to
adapt to your needs. Each `N`, of course, is that _compile-time_ constant that
you seek.

