2

I need to instantiate a free template function (FTF) within a template class (TC). The FTF takes as a template parameter one of the template parameters of the TC. The TC also holds generic pointers to these FTF's, and these functions are called through the pointers.

The step of taking a pointer to a FTF is not enough to instantiate it, and I receive linker errors from the GCC toolchain. MSDN illustrates FTF specification as so -- however my instantion of the FTF is dependant on a template parameter of my TC, and therefore the FTF instantiation cannot be placed in free scope.

Is this possible ? I am attaching some basic generated code, the issue is in the constructor of the class test_service, where I assign the pointer of a free function into a custom container. I get a linker error telling me the free function cannot be found (uninstantiated). I know that specifying a call to the template function in the class somewhere will produce a instantiation, however I am only going to be making a call via a pointer.

#include "rpc_common.h"
#include <boost/cstdint.hpp>

namespace rubble { namespace rpc {

  struct test_service_dummy_tag{};

  template<typename T>
  class test_service_skel
  {
  public:
    bool Init() {}
    bool TearDown() {}
    bool test_one(TestRequest,TestResponse){};
  private:
  };

  template<typename T_IMPL>
  bool test_service_test_one(T_IMPL & impl,ClientRequest & request)
  {
    return 0;
  }

  template<typename T_IMPL=test_service_skel<test_service_dummy_tag> >
  class test_service
  {
  public:
    test_service()
    {
      // uncomment the following two lines and a instantiation will occur.
      // ClientRequest cr;
      //test_service_test_one<T_IMPL>(m_impl,cr);
      m_dispatch_table.SetEntry( Oid("test_one",0),(void *)  & test_service_test_one<T_IMPL>);
    }
    bool Init() { return m_impl.Init(); };
    bool TearDown() { return m_impl.TearDown(); };
  private:
    T_IMPL m_impl;
    OidContainer<Oid,void *> m_dispatch_table;
  };


} }

EDIT: self-contained minimal version

 class test_skel
    {
      bool test_function()
      {
        return true;
      }
    };


    template<typename T>
    bool test_function()
    {

    }

    template<typename T = test_skel>
    class test
    {
    public:
      test()
      {
        dispatch = (void *) & test_function<T>;
      }
      void * dispatch;
    };

    int main()
    {
      test<> t;
      return 0;
    }
Hassan Syed
  • 20,075
  • 11
  • 87
  • 171
  • 1
    Could you possibly provide a **minimal** code example that illustrates your question? I think I have an idea, but I can't see through this verbose presentation just now. – Kerrek SB Jul 07 '11 at 11:31
  • done :D I am thinking static member functions might do the trick. – Hassan Syed Jul 07 '11 at 11:54

2 Answers2

2

There is no problem iff you don't use a void*, i.e.: http://www.ideone.com/eRgUG

However, if you insist on storing the pointer in a void*, then you need to take the address using a specific function pointer first and then cast - e.g.

    bool (*temp)() = &test_function<T>;
    dispatch = reinterpret_cast<void*>(temp); // YUCK

This gives the compiler enough context to generate the address for you.

Ahh - just saw DeadMG's answer, the function to generate the void* is neater...

Nim
  • 33,299
  • 2
  • 62
  • 101
1

Your self-contained example wouldn't compile for me with a strange error about overloaded functions, when there is no overloading going on, with MSVC. I did, however, manage to work around it.

class test_skel
{
    bool test_function()
    {
        return true;
    }
};

template<typename T> void* to_void_pointer(T t) {
    return reinterpret_cast<void*>(t);
}

template<typename T>
bool test_function()
{
    return true;
}

template<typename T = test_skel>
class test
{
public:
    test()
    {
        dispatch = to_void_pointer(&test_function<T>);
    }
    void * dispatch;
};

int main()
{
    test<> t;
    return 0;
}

This compiles cleanly. I suspect that whatever behaviour you're seeing and I saw is a compiler error.

Puppy
  • 144,682
  • 38
  • 256
  • 465
  • aha so it was a casting problem, I will be using a type-safe function pointer =D was being lazy while I was working on the code generator. – Hassan Syed Jul 07 '11 at 12:00
  • @Hassan: I don't see the relevance of defining the `test_skel` class, or how templates even matter in the example. After specifying the parameter, your `::test_function` is just an ordinary free function. – Kerrek SB Jul 07 '11 at 12:08