0

I want to pre create an array of template member function pointers, which will be indexed using a variable determined at run time by another class. The template functions can then be specialized.

This works in a non-template class, however I'm having issues in a template class. The applications has multiple mains which define different template arguments for MatchT, and this is hopefully representative in the code example:

#include Data.H  // POD object.
template<typename MatchT>
class Manager
{ 
    public:

    template <int P>
    bool do(Data& d_);

     template<int P, int ...Ps>
     struct table : table<P-1, P-1, Ps... >{};

     template<int... Ps>
     struct table <0, Ps...>
     {
          static constexpr bool(*fns[])(Data&)={do<Ps>...};
     };
  };

   template <typename MatchT>
   template<int... Ps>
   constexpr bool(*Manager<MatchT>::table<0,Ps...>::fns[sizeof...(Ps)])();


//process.h

 #include "Manager.H"

template<typename MatchT>
class Process
{
   public:

   void send(Manager<MatchT>& mgr  );

   private:

    typename Manager<MatchT>::template table<4> _processtable;
};

 //process.c

 template<typename MatchT>
 void Process<MatchT>::send(Manager<MatchT>& mgr)
 {
     ERROR here:
     mgr.*_processtable::fns[1]();
 }

ERROR:
In instantiation of "constexpr bool (* const Manager<MyManager<MyConfig>   >::table<0,0,1,2,3>::fns[4](Data&) 

required from "process.C"...
required from "manager.H" error no  matches converting function 'do' to     type 'bool (* const)(struct Data&)'
   static constexpr bool(*fns[])(Data&) = {do<Ps>...};
note:candidate  is: template<int P> bool Manager<MatchT>::do(Data&) [with int P = P; MatchT = DummyMatch]

  required from "process.C"...
required from "manager.H" error no  matches converting function 'do' to     type 'bool (* const)(struct Data&)'
   static constexpr bool(*fns[])(Data&) = {do<Ps>...};
note:candidate  is: template<int P> bool Manager<MatchT>::do(Data&) [with int P = P; MatchT = MyMatch<MyConfig> >]

I'm wondering if having the static static constexpr bool(*fns[])(Data&)={do<Ps>...}; in the template class is causing an issue. Is it not able to define the functions as static for each Manager<MatchT> type? What am I missing?

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
ggs
  • 41
  • 7
  • Did you mean `do` to be `static`? A non-static member function cannot convert to a function pointer. – aschepler Oct 27 '15 at 22:50
  • ah didn't catch that.. I can't make do static, because the code in the function refers to other members that I also can't make static. If I remove static from the declaration of fns, how do I then define it? – ggs Oct 27 '15 at 22:52
  • Ah, so you mean `fns` to be an array of pointers-to-member-functions, not function pointers. – aschepler Oct 27 '15 at 22:53
  • yes , sorry if that wasn't clear.. Also if I made do static, I'm not sure how I would refer to instance members inside do.. would it just be Manager::instanceMember ? Would that be correct for each MatchT ? – ggs Oct 27 '15 at 22:56
  • actually I have a simplified example of this working on a non template class, where the processTable is declared in main. The functions pointed to are not static within that class.. – ggs Oct 27 '15 at 22:58

1 Answers1

0

You declared and defined fns as an array of pointers to functions, when it really needs to be an array of pointers to member functions. Try:

template<typename MatchT>
class Manager
{ 
    public:

    template <int P>
    bool do(Data& d_);

     template<int P, int ...Ps>
     struct table : table<P-1, P-1, Ps... >{};

     template<int... Ps>
     struct table <0, Ps...>
     {
          static constexpr bool(Manager::*fns[])(Data&)={&Manager::do<Ps>...};
     };
};

template <typename MatchT>
template<int... Ps>
constexpr bool(Manager<MatchT>::*Manager<MatchT>::table<0,Ps...>::fns[sizeof...(Ps)])(Data&);
aschepler
  • 70,891
  • 9
  • 107
  • 161
  • actually sorry it does work, however I get a strange error for this line "mgr.*_processtable::fns[1]();". It's saying "error: must use '.*' or '->*' to call pointer-to-member function in 'Manager >::table<0,0,1,2,3>::fns[1] (...)', e.g. '(... ->* Manager >::table<0,0,1,2,3>::fns[1]) (...)' – ggs Oct 27 '15 at 23:43
  • @ggs `.*` binds less tightly than a function call, so you need parentheses. – Brian Bi Oct 27 '15 at 23:45
  • ah you're right! I just noticed that in aschepler's example. Thank you very much.. I was struggling with this. – ggs Oct 27 '15 at 23:49
  • last question to this.. if I want to use an enum instead of int for the 'P' and "Ps", so that when I specialize the functions I can use the enum type, is that possible? I tried but am getting errors "invalid conversion from 'int' to 'p_type' for the line "struct table : table{};" – ggs Oct 27 '15 at 23:55