1

I want to pass two functions with different signature into a same slot of class template parameter (one each time).

Ignore the strict syntax, this is what I want :-

void hf1 (int a)       { std::cout<< "hf1"    <<std::endl; }
void hf2 (int a, int i){ std::cout<< "hf2 "<<i<<std::endl; }
template<hfX> class Collection{
    int i_=56;
    public: test(){
        if( "hfX has 1 param" ){hfX(0);}   //call hf1
        else {hfX(0,i_);}                  //call hf2
    }
};
int main(){
    Collection<&hf1> test1; test1.test(); // print "hf1"
    Collection<&hf2> test2; test2.test(); // print "hf2 56"
}

Here is the code that works OK, but its usage is not so convenient :-

template<typename ... AA> using hfX = void(*)(AA ... );

void hf1 (int a)        { std::cout<< "hf1"     <<std::endl; }
void hf2 (int a, int i) { std::cout<< "hf2 "<<i <<std::endl; }

template <typename Tf, Tf F>
class Collection;

template <typename ... I, hfX<I...> F>
class Collection<hfX<I...>, F>{
   public: 
      int i_=56;
      template <std::size_t N = sizeof...(I)>
      typename std::enable_if<N == 1U, void>::type test (){
            F(0);
       }
      template <std::size_t N = sizeof...(I)>
      typename std::enable_if<N == 2U, void>::type test (){
           F(0,i_);
       }
 };

The usage:-

int main () {
   Collection<hfX<int>, hf1>      test1;      //<--- #A dirty signature
   Collection<hfX<int,int>, hf2>  test2;      //<--- #B dirty signature
   test1.test(); // print "hf1"
   test2.test(); // print "hf2 56"
 }

Live version : https://ideone.com/f20BEk

Question

It would be nice if I can call it without explicit redundant signature.

   Collection<hf1>  test1;     //or &hf 
   Collection<hf2>  test2;   

How to improve code (especially around hfX and Collection) to make its usage easier?

javaLover
  • 6,347
  • 2
  • 22
  • 67
  • This seems like an [XY problem](http://xyproblem.info/). What is the *actual* problem you want to solve with your solution? Also, the solution to the actual problem is probably a different design and not some code hacks (it has that "smell" to me). – Some programmer dude Jan 10 '17 at 05:20
  • @Some programmer dude This is sequel of a question. http://stackoverflow.com/questions/39507686/function-as-template-parameter-ift-receive-2-paramta-b-else-ta I agree that it is quite a hack and its smell is not so nice. However, I just want to know. I will decide later whether I should use it. :) – javaLover Jan 10 '17 at 05:22
  • 2
    @javaLover What you want isn't available till c++17 (auto non-type template parameters). You could probably done it with some macro in c++11 but I wouldn't recommend it... – W.F. Jan 10 '17 at 07:50
  • @W.F. Thank. It is good to know there is simply no nice way. – javaLover Jan 10 '17 at 07:51

1 Answers1

1

I don't know how to make what do you want with functions.

But if you can, instead of functions, accept to use static method in classes or structs (and pass that classes/structs as template argument)...

#include <iostream>

struct sf1
 { static void hf (int a) { std::cout << "hf1" << std::endl; } };

struct sf2
 { static void hf (int a, int i) { std::cout << "hf2 " << i << std::endl; } };

template <typename S>
class Collection
 {
   private: 
      int i_ = 56;

   public:
      template <typename T = S>
      decltype(T::hf(0)) test() { S::hf(0); /*call sf1::hf */ }

      template <typename T = S>
      decltype(T::hf(0, 0)) test() { S::hf(0,i_); /*call sf2::hf */ }
 };

int main ()
 {
   Collection<sf1> test1; test1.test(); // print "hf1"
   Collection<sf2> test2; test2.test(); // print "hf2 56"
 }
max66
  • 65,235
  • 10
  • 71
  • 111