作为模板参数的函数: if(T receive 2 param)T(a,b);否则 T(a);
Posted
技术标签:
【中文标题】作为模板参数的函数: if(T receive 2 param)T(a,b);否则 T(a);【英文标题】:function as template parameter : if(T receive 2 param)T(a,b); else 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<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 的答案是可以的,但不太可取。
我觉得可以通过“默认参数”的技巧来解决。
【问题讨论】:
IIRC,std::bind
已经支持忽略其他参数:coliru.stacked-crooked.com/a/ab538d4302311c64
@dyp 谢谢。它是如此接近,但我不知道如何将它用于这种情况(模板)。而且,在调用类的时候是不是需要修改(所以这个类的很多用户都要修改)?我想听听。 :)
【参考方案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"
【讨论】:
以上是关于作为模板参数的函数: if(T receive 2 param)T(a,b);否则 T(a);的主要内容,如果未能解决你的问题,请参考以下文章
从std :: function中推导返回和参数类型作为模板函数参数传递?