2016-09-15 4 views
3

Как создать класс шаблона Collection<K,T> получить функцию T - это может либо иметь подпись T(K), либо T(K,int) - в качестве аргумента шаблона, то условно скомпилировать базу подписи функции?Функция в качестве параметра шаблона: if (T получает 2 параметра) 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 в порядке, но менее предпочтительным.

Я чувствую, что он может быть разрешен с помощью трюка «default parameter».

+0

IIRC, 'станд :: 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" 
} 
Смежные вопросы