【问题标题】:function as template parameter : if(T receive 2 param)T(a,b); else T(a);作为模板参数的函数: if(T receive 2 param)T(a,b);否则 T(a);
【发布时间】:2016-09-15 09:34:10
【问题描述】:

如何使模板类Collection<K,T> 接收一个函数T - 可以具有签名T(K)T(K,int) - 作为模板参数,然后根据函数的签名有条件地编译?

这是可以接收 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&lt;K,HashFunction(K,int)&gt;

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 个不同的类:Collection1Collection2
需要超过 c++11 的答案是可以的,但不太可取。

我觉得可以通过“默认参数”的技巧来解决。

【问题讨论】:

  • IIRC,std::bind 已经支持忽略其他参数:coliru.stacked-crooked.com/a/ab538d4302311c64
  • @dyp 谢谢。它是如此接近,但我不知道如何将它用于这种情况(模板)。而且,在调用类的时候是不是需要修改(所以这个类的很多用户都要修改)?我想听听。 :)

标签: c++ templates c++11 template-classes


【解决方案1】:

可变参数模板、偏特化和 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"
 }

【讨论】:

    猜你喜欢
    • 2012-07-29
    • 2012-04-07
    • 2022-10-13
    • 1970-01-01
    • 2018-01-12
    • 1970-01-01
    • 2018-05-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多