模板功能专门化/重载 [英] Template function specialization/overloading

查看:54
本文介绍了模板功能专门化/重载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正面临以下情况:我有一个类'''',它实现了一些概念C - 但我们知道这一点,不是因为A继承自

虚拟班级''C'',但仅仅因为一个特质告诉我们:


A级{};


模板< typename T>

struct Is_C

{

static const bool value = false;

};


模板<>

struct Is_C< A>

{

static const bool value = true;

};

我想做的是,给定A的实例''a',调用函数

''foo(a)''将具有A类的特定代码 - 并且具有其他类的默认

代码。


以下


模板< typename T>

void foo(T t)

{

if(Is_C< T> :: value)

{

/ * ... * /

}

其他

{

/ * ... * /

}

}


会起作用,但是,它不是除非我修改函数foo,否则可扩展到另一个特征''Is_D''

。理想情况下,对于一般情况(对应于''else''),我会有一个函数foo

和所有不同测试的多个

函数foo,但是我我不知道怎么办

那个。我想使用boost :: enable_if,但是如果我使用函数

重载,我需要在我的''一般情况''foo中使用disable_if来获取

每个''专业''foo:


//一般情况

模板< typename T>

typename disable_if< Is_C< T> > ::类型//必须修改如果

另外添加foo

foo(T t)

{

/ * ... * /

}


//概念专业化C

模板< typename T>

typename enable_if< Is_C< T> > ::类型

foo(T t)

{

/ * ... * /

}


我真的很感激任何关于这个问题的建议。


谢谢


B.

解决方案

ga *** ****@voila.fr 写道:

我面临以下情况:我有一个类'''',它实现了一些概念C - 但是我们知道这一点,不是因为A继承了虚拟类'C',而只是因为一个特性告诉了我们:

A类}}}

模板< typename T>
struct Is_C
{
static const bool value = false;
};

模板<>
struct Is_C< A>
{
静态const bool值= true;
};

我想做的是,给定一个实例A的''a',调用一个函数
''foo(a)''将具有特定的clas代码s - 并且有其他类的默认代码。

以下

模板< typename T>
void foo(T t)
{
if(Is_C< T> :: value)
{
/ * ... * /
}

{
/ * ... * /
}
}

会起作用,但是除非我修改函数foo,否则不能扩展到另一个特征''Is_D''
。理想情况下,对于一般情况(对应于''else''),我会有一个函数foo
,对于所有不同的测试,我会有很多
函数foo,但我不知道怎么做重载,我需要在我的''一般情况''foo中有一个disable_if用于
每个''special''foo:

//一般案例
模板< typename T>
typename disable_if< Is_C< T> > :: type //如果添加了另一个foo,则必须修改它。
foo(T t)
{
/ * ... * /
}

//概念专业化C
模板< typename T>
typename enable_if< Is_C< T> > ::类型
foo(T t)
{
/ * ... * /
}

我真的很感激任何建议这个问题。


有趣的问题。当然,我想说的第一个想法就是

你自己和其他人都在混淆你的特质。 ''Is_C''或

''Is_D''。显然你的班级A _isn''t_ C或D,否则继承

应该可以正常工作。您应该将您的概念命名为原样,

类似'implements_C''或'implements_D''。


无论如何......我想到了为你的''foo''提供帮助:

------------------------------- -----------------------------------------

#包括< iostream>


模板< class T> struct implements_C {enum {value = 0}; };


模板< class T,bool b> struct foo_helper {

static void foo(T t)

{

std :: cout<< Generic foo \ n;

}

};


模板< class T> struct foo_helper< T,true> {

static void foo(T t)

{

std :: cout<< "''true'' - 具体foo \ n" ;;

}

};


模板< class T> ; void foo(T t)

{

foo_helper< T,implements_C< T> :: value> :: foo(t);

}


A级{};

B级{};


模板<> struct implement_C< A> {enum {value = 1}; };


int main()

{

A a;

foo(a) ;

B b;

foo(b);

}

-------- -------------------------------------------------- --------------


现在,如果你需要添加另一个策略,那就是''foo_helper'',它确实是

实际工作,不应该改变。你改变的是''foo'':

模板< class T> void foo(T t)

{

foo_helper< T,

implements_C< T> :: value || implements_D< T> :: value :: foo(t);



}


这是修改后的代码,包含两个策略:

--------------------------------------------- ---------------------------

#include< iostream>


模板< class T> struct implements_C {enum {value = 0}; };

模板< class T> struct implements_D {enum {value = 0}; };


模板< class T,bool b> struct foo_helper {

static void foo(T t)

{

std :: cout<< Generic foo \ n;

}

};


模板< class T> struct foo_helper< T,true> {

static void foo(T t)

{

std :: cout<< "''true'' - 具体foo \ n" ;;

}

};


模板< class T> ; void foo(T t)

{

foo_helper< T,implements_C< T> :: value || implements_D< T> :: value> :: foo(t);

}


class A {};

B级{};

类AB {};

类C {};


模板<> struct implement_C< A> {enum {value = 1}; };

模板<> struct implements_D< B> {enum {value = 1}; };

模板<> struct implements_C< AB> {enum {value = 1}; };

模板<> struct implements_D< AB> {enum {value = 1}; };


int main()

{

A a;

foo(a) ;

B b;

foo(b);

AB ab;

foo(ab);

C c;

foo(c);

}

---------- -------------------------------------------------- --------


HTH


V


谢谢为你的答案。但是,我的问题略有不同 -

让我进一步解释。我想保留开放的可能性,以便添加一个

第三个函数foo,以防有人想出另一个概念D for

foo应该以不同的方式实现。例如:


//一般情况

模板< typename T>

//添加第三个foo时修改了以下行

typename disable_if< implements_C< T> || implements_D< T> > ::类型

foo(T t)

{

/ * ... * /

}


//概念专业化C

模板< typename T>

typename enable_if< implements_C< T> > ::类型

foo(T t)

{

/ * ... * /

}


//概念专业化D

模板< typename T>

typename enable_if< implements_D< T> > ::类型

foo(T t)

{

/ * ... * /

}

人们可以通过用整数替换bool

来概括你的辅助函数的想法,但我不喜欢不得不修改帮助器的想法

函数 - 从这个意义上说,我不确定你有什么好处

方法与之前的函数集相比。理想情况下

有人应该能够添加''foo'',而无需修改剩余的代码




ga*******@voila.fr 写道:

感谢您的回答。但是,我的问题略有不同 -
让我进一步解释。我想留下可能性增加第三个函数foo的可能性,以防有人想出另一个概念D,其中foo应该以不同的方式实现。



您需要的是通过在您的特质中添加''标签'

类来实现。例如,这里有一些伪代码:


struct ATag {};

struct BTag {};

struct CTag {};


模板< typename TYPE>

struct Traits;


class SomeClassThatHasATrait {... };

class SomeClassThatHasBTrait {...};

class SomeClassThatHasCTrait {...};


template<> ;

struct Traits< SomeClassThatHasATrait> {typedef ATag Tag; };


模板<>

struct Traits< SomeClassThatHasBTrait> {typedef BTag Tag; } b / b
struct traits< SomeClassThatHasCTrait> {typedef CTag Tag; };


模板< typename TYPE>

void foo(TYPE对象,ATag)

{

...具有A特性的类型的代码....

}


模板< typename TYPE>

void foo(TYPE对象,BTag)

{

...具有B特征的类型的代码....

}


模板< typename TYPE>

void foo(TYPE对象,CTag)

{

...具有C特性的类型的代码....

}


模板< typename TYPE>

void foo(TYPE对象)

{

typedef typename Traits< TYPE> :: Tag Tag;

foo(object,Tag()) ;

}


---------------------------- -------------


现在,当你想添加一个新的''D''特征时,你所要做的就是定义

a标签:


struct DTag {};


定义一些具有D特性的类:


clas s SomeClassThatHasDTrait {...};


模板<>

struct Traits< SomeClassThatHasDTrait> {typedef DTag Tag;接下来,为具有D特征的类定义一个foo函数:


模板< typename TYPE>

void foo(TYPE对象,DTag)

{

...具有C特性的类型的代码....

}

希望这有帮助,

-shez-


I am facing the following scenario: I have a class ''A'', that implements
some concept C -- but we know this, not because A inherits from a
virtual class ''C'', but only because a trait tell us so:

class A {};

template <typename T>
struct Is_C
{
static const bool value = false;
};

template <>
struct Is_C<A>
{
static const bool value = true;
};
What I would like to do is, given an instance ''a'' of A, call a function
''foo(a)'' that would have specific code for class A -- and have default
code for other classes.

The following

template < typename T >
void foo(T t)
{
if (Is_C<T>::value)
{
/* ... */
}
else
{
/* ... */
}
}

would work, but then, it is not extensible to another trait ''Is_D''
unless I modify the function foo. Ideally I would have a function foo
for the general case (corresponding to the ''else'') and as many
functions foo for all the different tests, but I am not sure how to do
that. I would like to use the boost::enable_if, but if I use function
overloading, I need to have a disable_if in my ''general case'' foo for
each ''specialized'' foo:

// General case
template < typename T >
typename disable_if<Is_C<T> >::type // This has to be modified if
another foo is added
foo(T t)
{
/* ... */
}

// Specialization for concept C
template < typename T >
typename enable_if<Is_C<T> >::type
foo(T t)
{
/* ... */
}

I would really appreciate any suggestion for this problem.

Thanks

B.

解决方案

ga*******@voila.fr wrote:

I am facing the following scenario: I have a class ''A'', that implements
some concept C -- but we know this, not because A inherits from a
virtual class ''C'', but only because a trait tell us so:

class A {};

template <typename T>
struct Is_C
{
static const bool value = false;
};

template <>
struct Is_C<A>
{
static const bool value = true;
};
What I would like to do is, given an instance ''a'' of A, call a function
''foo(a)'' that would have specific code for class A -- and have default
code for other classes.

The following

template < typename T >
void foo(T t)
{
if (Is_C<T>::value)
{
/* ... */
}
else
{
/* ... */
}
}

would work, but then, it is not extensible to another trait ''Is_D''
unless I modify the function foo. Ideally I would have a function foo
for the general case (corresponding to the ''else'') and as many
functions foo for all the different tests, but I am not sure how to do
that. I would like to use the boost::enable_if, but if I use function
overloading, I need to have a disable_if in my ''general case'' foo for
each ''specialized'' foo:

// General case
template < typename T >
typename disable_if<Is_C<T> >::type // This has to be modified if
another foo is added
foo(T t)
{
/* ... */
}

// Specialization for concept C
template < typename T >
typename enable_if<Is_C<T> >::type
foo(T t)
{
/* ... */
}

I would really appreciate any suggestion for this problem.
Interesting problem. Of course, the first think I want to say is that
you''re confusing yourself and others calling your "traits" ''Is_C'' or
''Is_D''. Apparently your class A _isn''t_ C or D, otherwise inheritance
should work just fine. You should name your concept as it is, something
like ''implements_C'' or ''implements_D''.

Anyway... I thought of providing the helper for your ''foo'':
------------------------------------------------------------------------
#include <iostream>

template<class T> struct implements_C { enum { value = 0 }; };

template<class T, bool b> struct foo_helper {
static void foo(T t)
{
std::cout << "Generic foo\n";
}
};

template<class T> struct foo_helper<T, true> {
static void foo(T t)
{
std::cout << "''true''-specific foo\n";
}
};

template<class T> void foo(T t)
{
foo_helper<T, implements_C<T>::value>::foo(t);
}

class A {};
class B {};

template<> struct implements_C<A> { enum { value = 1 }; };

int main()
{
A a;
foo(a);
B b;
foo(b);
}
------------------------------------------------------------------------

Now, if you need to add another "policy", the ''foo_helper'', which does
the actual work, shouldn''t change. What you change is the ''foo'':
template<class T> void foo(T t)
{
foo_helper<T,
implements_C<T>::value || implements_D<T>::value::foo(t);


}

Here is amended code with two policies:
------------------------------------------------------------------------
#include <iostream>

template<class T> struct implements_C { enum { value = 0 }; };
template<class T> struct implements_D { enum { value = 0 }; };

template<class T, bool b> struct foo_helper {
static void foo(T t)
{
std::cout << "Generic foo\n";
}
};

template<class T> struct foo_helper<T, true> {
static void foo(T t)
{
std::cout << "''true''-specific foo\n";
}
};

template<class T> void foo(T t)
{
foo_helper<T, implements_C<T>::value || implements_D<T>::value >::foo(t);
}

class A {};
class B {};
class AB {};
class C {};

template<> struct implements_C<A> { enum { value = 1 }; };
template<> struct implements_D<B> { enum { value = 1 }; };
template<> struct implements_C<AB> { enum { value = 1 }; };
template<> struct implements_D<AB> { enum { value = 1 }; };

int main()
{
A a;
foo(a);
B b;
foo(b);
AB ab;
foo(ab);
C c;
foo(c);
}
--------------------------------------------------------------------

HTH

V


Thanks for your answer. However, my problem is slightly different --
let me explain further. I want to leave the possibility open to add a
third function foo in case somebody comes up with another concept D for
which foo should be implemented differently. E.g:

// General case
template < typename T >
// the following line has been modify when third foo was added
typename disable_if<implements_C<T> || implements_D<T> >::type
foo(T t)
{
/* ... */
}

// Specialization for concept C
template < typename T >
typename enable_if<implements_C<T> >::type
foo(T t)
{
/* ... */
}

// Specialization for concept D
template < typename T >
typename enable_if<implements_D<T> >::type
foo(T t)
{
/* ... */
}
One could generalize your idea of helper functions by replacing a bool
by an integer, but I don''t like the idea of having to modify the helper
function -- in that sense, I am not sure what benefits come from you
approach compared to the previous collection of functions. Ideally
somebody should be able to add a ''foo'' without having to modify the
remaining of the code.


ga*******@voila.fr wrote:

Thanks for your answer. However, my problem is slightly different --
let me explain further. I want to leave the possibility open to add a
third function foo in case somebody comes up with another concept D for
which foo should be implemented differently.


What you need could be achieved by adding a ''tag'' inside your traits
class. For example, here''s some pseudocode:

struct ATag { };
struct BTag { };
struct CTag { };

template <typename TYPE>
struct Traits;

class SomeClassThatHasATrait { ... };
class SomeClassThatHasBTrait { ... };
class SomeClassThatHasCTrait { ... };

template <>
struct Traits<SomeClassThatHasATrait> { typedef ATag Tag; };

template <>
struct Traits<SomeClassThatHasBTrait> { typedef BTag Tag; };

template <>
struct Traits<SomeClassThatHasCTrait> { typedef CTag Tag; };

template <typename TYPE>
void foo(TYPE object, ATag)
{
... code for types that have A trait ....
}

template <typename TYPE>
void foo(TYPE object, BTag)
{
... code for types that have B trait ....
}

template <typename TYPE>
void foo(TYPE object, CTag)
{
... code for types that have C trait ....
}

template <typename TYPE>
void foo(TYPE object)
{
typedef typename Traits<TYPE>::Tag Tag;
foo(object, Tag());
}

-----------------------------------------

Now, when you want to add a new ''D'' trait, all you have to do is define
a tag for it:

struct DTag { };

Define some class that has the D trait:

class SomeClassThatHasDTrait { ... };

template <>
struct Traits<SomeClassThatHasDTrait> { typedef DTag Tag; };

Next, define a foo function for classes that have the D trait:

template <typename TYPE>
void foo(TYPE object, DTag)
{
... code for types that have C trait ....
}
Hope this helps,
-shez-


这篇关于模板功能专门化/重载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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