2016-09-15 100 views
3

如何使模板類Collection<K,T>接收函數T - 可以有簽名T(K)T(K,int) - 作爲模板參數,然後有條件地編譯基於函數的簽名?作爲模板參數:if(T receive 2 param)T(a,b);否則T(a);

以下是可以接收1個簽名的現有代碼:Collection<K,HashFunction(K)>

template<typename AA> using HashFunction= HashStruct& (*)(AA); 
/** This class is currently used in so many places in codebase. */ 
template<class K,HashFunction<K> T> class Collection{ 
    void testCase(){ 
     K k=K(); 
     HashStruct& hh= T(k);      /*Collection1*/ 
     //.... something complex ... 
    } 
}; 

我希望它也支持Collection<K,HashFunction(K,int)>

template<class K,HashFunction<K> T /* ??? */> class Collection{ 
    int indexHash=1245323; 
    void testCase(){ 
     K k=K(); 
     if(T receive 2 parameter){  // ??? 
      HashStruct& hh=T(k,this->indexHash); /*Collection2*/ // ??? 
       //^ This is the heart of what I really want to achieve. 
       //.... something complex (same) ... 
     }else{ 
      HashStruct& hh=T(k);     /*Collection1*/ 
       //.... something complex (same) ... 
     } 
    } 
}; 

難道我沒有選擇,而是要創造2個不同的類別:Collection1 & Collection2
需要比C++ 11更好的答案是可以的,但不太可取。

我覺得它可以通過使用「默認參數」技巧解決。

+0

IIRC,'的std :: bind'已經有忽略其他參數一定的支持:http://coliru.stacked-crooked.com/a/ab538d4302311c64 – dyp

+0

@dyp謝謝。它非常接近,但我不知道如何將其應用於此案例(模板)。而且,調用類時不需要修改(因此,需要修改這個類的許多用戶)。我想聽聽。 :) – javaLover

回答

1

Variadic模板,部分專業化和SFINAE可以幫助你。

如果接受複製的test()方法,你可以這樣做

#include <iostream> 

using HashStruct = std::size_t; 

template<typename ... AA> 
using HashFunction = HashStruct & (*)(AA ...); 

HashStruct & hf1 (std::size_t s) 
{ static HashStruct val {0U}; return val = s; } 

HashStruct & hf2 (std::size_t s, int i) 
{ static HashStruct val {0U}; return val = s + std::size_t(i); } 

template <typename Tf, Tf F> 
class Collection; 

template <typename K, typename ... I, HashFunction<K, I...> F> 
class Collection<HashFunction<K, I...>, F> 
{ 
    public: 

     template <std::size_t N = sizeof...(I)> 
     typename std::enable_if<N == 0U, void>::type test() 
     { 
     K k=K(); 

     HashStruct & hh = F(k); 

     std::cout << "case 0 (" << hh << ")" << std::endl; 
     } 

     template <std::size_t N = sizeof...(I)> 
     typename std::enable_if<N == 1U, void>::type test() 
     { 
     K k=K(); 

     HashStruct & hh = F(k, 100); 

     std::cout << "case 1 (" << hh << ")" << std::endl; 
     } 
}; 

int main() 
{ 
    Collection<HashFunction<std::size_t>, hf1>  c1; 
    Collection<HashFunction<std::size_t, int>, hf2> c2; 

    c1.test(); // print "case 0 (0)" 
    c2.test(); // print "case 1 (100)" 
} 

但是,如果你可以通過額外的參數test(),你不需要SFINAE,你可以創建一個test()方法都是簡單的

#include <iostream> 

using HashStruct = std::size_t; 

template<typename ... AA> 
using HashFunction = HashStruct & (*)(AA ...); 

HashStruct & hf1 (std::size_t s) 
{ static HashStruct val {0U}; return val = s; } 

HashStruct & hf2 (std::size_t s, int i) 
{ static HashStruct val {0U}; return val = s + std::size_t(i); } 

template <typename Tf, Tf F> 
class Collection; 

template <typename K, typename ... I, HashFunction<K, I...> F> 
class Collection<HashFunction<K, I...>, F> 
{ 
    public: 
     void test (I ... i) 
     { 
     K k=K(); 

     HashStruct & hh = F(k, i...); 

     std::cout << hh << std::endl; 
     } 
}; 

int main() 
{ 
    Collection<HashFunction<std::size_t>, hf1>  c1; 
    Collection<HashFunction<std::size_t, int>, hf2> c2; 

    c1.test(); // print "0" 
    c2.test(100); // print "100" 
} 
相關問題