none
Passing a function as template argument RRS feed

  • Question

  • It is VC++ project under VS 2019 Community Update 16.6.4, Win 10.

    I have a set of classes in type list:

    class L
    {
    public:
      static int GetInt() {return m_Int;]
      static double GetDbl() {return m_Dbl;}
    
    private:
      static int m_Int;
      static double m_Dbl;
    };
    
    template<typename H, typename... Hs>
    struct tlist {};
    
    using MyHs = tlis<H, Hs...>;


    Classes Hs all have the same structure as class L, but they are not derived from the same base class.

    Now, what I would like to hae somewhere in code:

    template <template <typename> typename Fn, typename Lst> struct Vectorize; template <typename H, typename Fn, typename... Hs> struct Vectorize<Fn<H>, tlist<H, Hs...>> { staic inline void FnV(std::vector<Fn::res_type>& vRes) { vRes>pussh_back(Fn(); if connstexpr (siseof...(Hs) > 0) Vectorize<Fn, tlist<Hs..>::Fn(vvRes); } };


    and later write somethig like

    template <typename H> Fh<H> = H::getInt; vector< int> vResI;

    Vectorize<Fn<H>, MyHs>::Fn(vResIesI);


    And the similar for GetDbl.

    I do not know how to pass something like generic function as template parameter.

    Any help is very appresiated.


    • Edited by Geoyar Saturday, August 1, 2020 1:17 AM
    Saturday, August 1, 2020 1:14 AM

All replies

  • You show class L, and apparently you wish to call L::GetInt , but nowhere in the code shown is this class actually used. How does it get into the picture? Imagine that you've somehow managed to implement Vectorize the way you want - show how the caller would actually use it, and explain what outcome you would expect from this usage. None of this is clear from your question.

    Igor Tandetnik

    Saturday, August 1, 2020 4:14 AM
  • Thank you for replay.

    What I want:

    Suppose I successfully wrote a template

    template <class Fn, class Lst
    struct Vectorize;
    
    template <class H, template<typename> class Fn, class... Hs>
    struct Vectorize<Fn<H> tlist<H, Hs...>>
    {
      static inline void FnL<vector <Fn<H>::result_type>& vRes)
      {
         vRes::push_bach(Fn<H>();
     
        if constexpr(sizeof...(Hs) > 1)
                repeat on Hs
       }
    };

    Then I can write

    template<class H> 
    function <int(void)> AccessInt = H::GetInt;


    and call Vectorize<AccessInt<H>, tlistst<H, Hs...>>;

    Next time I would use

    template <class H>
    function<double(void))> AccessDoub;e = H:GetDouble;

    etc.

    I do not know to pass

    template<class H, class R>

    function<R(void)> Access;

    Saturday, August 1, 2020 9:13 PM
  • In the supposed call to Vectorize<AccessInt<H>, tlistst<H, Hs...>> , what's H and Hs ? What is the expected outcome? What's the purpose of this call - once everything is said and done, what do you want it to produce?

    I still don't see where L is mentioned.

    Igor Tandetnik

    Sunday, August 2, 2020 1:42 AM
  • Suppose I have four classes, H0, H1, H2, H3.

    Then to would be template I will pass H0, H1, H2, H3 as tlist<H0, H1, H2, H3> and H0 stays for H.Than for GetInt I want to have vector<int>vRes, and vRes.push_back(H0::GetInt();

    For second iteration H is replaced by H1, and vRes.push_back(H1::GetInt(); Ans the same for H2, H3

    Of course, parameter Fn must be specialized as, say,

    template<typename H>

    function<int(void)> FnInt = H::GetInt;

    For GetDbl I will have vector<double> vRes, and push_back(H0::GetDbl())

    and

    template <typename H>

    function<double(void)> FnDbl = H::GetDbl;

    The result will be vctor<int> vRes or vector<double> vRes.

    I can write separate templates that have arguments FnInt, FnDbl, but then I will have to place the same code inside 

    What I want is to have generic Fn template argument and repace it with FnInt, FnDbl in in template instantiation. 

    Sunday, August 2, 2020 3:25 AM
  • Something along these lines, perhaps:

    #include <vector>
    #include <iostream>
    
    class H0 {
    public:
      static int GetInt() {return 0;}
      static double GetDbl() {return 0;}
    };
    
    class H1 {
    public:
      static int GetInt() {return 1;}
      static double GetDbl() {return 1;}
    };
    
    template <typename H>
    struct GetIntFun {
        static constexpr auto call = H::GetInt;
    };
    
    template <typename H>
    struct GetDblFun {
        static constexpr auto call = H::GetDbl;
    };
    
    
    template <template <typename> class Fn, typename... Hs, typename C>
    void Vectorize(C& vec) {
        vec.insert(vec.end(), {Fn<Hs>::call()...});
    }
    
    int main() {
        std::vector<int> vi;
        Vectorize<GetIntFun, H0, H1>(vi);
        std::cout << vi[0] << ' ' << vi[1] << std::endl;
    
        std::vector<double> vd;
        Vectorize<GetDblFun, H0, H1>(vd);
        std::cout << vd[0] << ' ' << vd[1] << std::endl;
    }

    Demo


    Igor Tandetnik


    Sunday, August 2, 2020 12:30 PM
  • First, thank for replay.

    I hope it is working, but it is not what I am looking for.

    As I understand it, we have to write accessor for each name of member function in our classes we have to vectorize. Of course, we can write accessors for types of functions we need,  like int(*fn(void))(), bool(*fn(void))() etc.. 

    It seems that we have to use pointers to functions. For now I got only so far:

    template <typename type, type(*ptr)()>
    struct test
    {
      static inline type Fn()
      {
        return ptr();
      }
    };
    
    class L1
    {
       static inline double GetPollingFactor() {return 0.25;}
       static inline bool HasInt() {reurn false;}
    };
    
    int main()
    (
      auto resDbl = test<double, L1::GetPollingFactor>::Fn();
      auto resBool = test<bool, L1::HasInt>::Fn();
    
    }
    
    

    I should templatize the 'test' for type name L, and Ls. Obviously, member function inside templat can do whar needed.

    Again, any help is very appreciated.

    Monday, August 3, 2020 10:10 PM
  • My example does in fact use pointers to function (GetIntFun::call and GetDblFun::call are such). I'm not sure I quite grasp the nature of your objections. In what way does my example fail to meet your requirements? What is it you want to achieve, that this approach won't let you?

    Writing

    auto resDbl = test<double, L1::GetPollingFactor>::Fn();

    seems kinda pointless, since it's exactly equivalent to

    auto resDbl = L1::GetPollingFactor();

    So I'm not sure what this example was supposed to demonstrate.


    Igor Tandetnik

    Tuesday, August 4, 2020 1:32 PM