用作模板参数:if(T接收2个参数)T(a,b);否则T(a); [英] function as template parameter : if(T receive 2 param)T(a,b); else T(a);

查看:88
本文介绍了用作模板参数:if(T接收2个参数)T(a,b);否则T(a);的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

How to make template class Collection<K,T> receive a function T - that can either has signature T(K) or T(K,int) - as template argument, then conditionally compile base on the signature of the function?

这是可以接收1个签名的现有代码: Collection< K,HashFunction(K)>

Here is the existing code that can receive 1 signature : 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) ... 
        }
    }
};

我别无选择,只能创建两个不同的类: Collection1 & Collection2

需要超过c ++ 11的答案是可以的,但不太可取。

Do I have no choice but to create 2 different classes : Collection1 & Collection2?
Answer that need more than c++11 is ok but less preferable.

我认为可以使用默认参数技巧来解决。

I feel that it might be solvable by using "default parameter" trick.

推荐答案

可变参数模板,部分专业化和SFINAE可以

Variadic templates, partial specialization and SFINAE can help you.

如果您接受重复 test()方法,则可以执行类似的操作

If you accept to duplicate the test() method, you can do something like

#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()方法一切都更简单

But, if you can pass the extra argument to test(), you don't need SFINAE, you can create a single test() method and all is simpler

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

这篇关于用作模板参数:if(T接收2个参数)T(a,b);否则T(a);的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆