将f(a)和f(a,b)作为模板参数的相同槽传递:不需要显式签名传递

时间:2017-01-10 05:16:59

标签: c++11 sfinae

我想将具有不同签名的两个函数传递到类模板参数的同一个槽中(每次一个)。

忽略严格的语法,这就是我想要的: -

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"
}

这是可行的代码,但它的用法不太方便: -

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_);
       }
 };

用法: -

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"
 }

实时版:https://ideone.com/f20BEk

问题

如果我可以在没有明确冗余签名的情况下调用它,那将是很好的。

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

如何改进代码(特别是在hfXCollection附近)以简化其使用?

1 个答案:

答案 0 :(得分: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"
 }