模板参数匹配 [英] Template argument matching

查看:64
本文介绍了模板参数匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



请查看以下代码:


模板< typename T,typename Enable = void>

级A

{

public:

enum {value = 0};

};


模板< typename T>

A类< T,typename T ::启用>

{

公开:

enum {value = 1};

};


B级

{

public:

typedef void Enable;

};


class C
{

};


int main(int argc,char * argv [])

{

int b = A< B> :: value; //应为1

int c = A< C> :: value; //应该是0

返回0;

}


这里的目标是创建一个名为A的类模板如果T :: Enable存在,那么

A< T> :: value是1的方式,否则为0。我已经在MSVC ++ 7.1上尝试了这个

,它确实有效,但只有当T :: Enable与

完全相同时,才能使用与默认值相同的类型模板参数

A.例如,如果我将B中的typedef更改为

typedef int Enable; // int而不是void

那么main中变量b的值将为0.


我想知道为什么'那个' 。我认为专业化将是

更好地匹配T :: Enable存在的所有类型,无论它实际上是什么类型的b $ b类型。而且我无法真正看到与

第二个模板参数的关联。


Imre

解决方案



Imre写道:

请看下面的代码:

template< ; typename T,typename Enable = void>
A级
{
公开:
enum {value = 0};
};
template< typename T>
A类< T,typename T :: Enable>
{
公开:
enum {value = 1};
};

B班
{
公开:
typedef void启用;
};

C类
{
};

int main(int argc,char * argv [])
{
int b = A< B> :: value; //应该是1
int c = A< C> :: value; //应该是0
返回0;
}
这里的目标是以一种方式创建一个名为A的类模板
A< T> ::如果T :: Enable存在,则值为1,否则为0。我在MSVC ++ 7.1上尝试了
,它确实有效,但只有当T :: Enable是

A的启用模板参数的默认值完全相同时例如,如果我将B中的typedef更改为
typedef int Enable; // int而不是void
那么main中变量b的值将为0.

我想知道为什么'那样。我认为专门化将
更好地匹配T :: Enable存在的所有类型,无论
它实际意味着什么类型。而且我无法真正看到与
连接的第二个模板参数。

Imre




我在猜你真正想要的是一个特质:


.. #include< iostream>

..

。 。template< typename T>

.. class Trait

.. {

.. public:

..枚举{ENABLE = 0};

..};


这定义了一个特征,默认情况下为零。现在你可以定义你的

''''这样的类:


.. template< typename T,typename T2 = Trait< T> >

.. A级

.. {

.. public:

.. enum {value = T2 :: ENABLE};

..};


从Trait类中的''ENABLE''枚举中获取''value'' (默认情况下,这是
零)。现在你可以创建你的其他课程:


.. class B {};

.. class C {};


现在,专门化Trait< T>所以''ENABLE''设置为一个'B'类':


..模板<>

..类Trait< ; B>

.. {

.. public:

.. enum {ENABLE = 1};

..};


这意味着''B''现在可以用于'A'中你想做的任何事情。


.. int main(int argc,char * argv [])

.. {

.. int b = A< B> :: value; //应该是1

.. int c = A< C> :: value; //应该是0

..

.. std :: cout<< b<< " " << c<< std :: endl;

..

..返回0;

..}

这应该打印out1 0 (正如预期的那样)。


希望这会有所帮助,

-shez-


我认为您可能会将默认模板

参数与部分模板专业化混淆。


如果您查看上面的代码,两者都不是lines:

int b = A< B> :: value; //应该是1
int c = A< C> :: value; //应为0


明确提供原始模板的启用参数。


出于这个原因,你有隐含的书面形式:


int b = A< B,void> :: value;

int c = A< C,void> :: value;
类型为void。

当编译器决定是否使用

部分模板专门化时:

模板< typename T>
A类< T,typename T ::启用>
{
公开:
枚举{value = 1};
};


T :: Enable必须是void类型才能选择专门的




如果你写:


B级

{

public:

typedef int Enable;

};


然后是隐式写的行:


int b = A< B,void>: :value;


不使用部分模板专业化:

模板< typename T>
A类< T,typename T ::启用>
{
公开:
枚举{value = 1};
};




因为T ::启用(真正的B ::启用)是int类型,第二个

参数是A< B,void>属于void类型。换句话说,由于void是第二个模板参数的类型,因此无法应用类型为int

的T :: Enable,并且无法选择特化,因为

类型冲突。


我希望这有帮助! =)


Michael Loritsch




Shezan Baig写道:

这定义了一个特征,默认情况下为零。现在你可以像这样定义你的'A'类了:

。 template< typename T,typename T2 = Trait< T> >
。 A级
。 {
。公众:
。枚举{value = T2 :: ENABLE};
。 };




另外,如果你想为ENABLE = 1设置一个单独的专业化(在原帖中为

),你可以这样做:


..模板< typename T,

.. typename T2 = Trait< T>,

。 .int ENABLE = T2 :: ENABLE>

.. A级

.. {

.. public:

.. enum {value = 0};

..};

..

.. template< typename T, typename T2>

.. A类< T,T2,1>

.. {

.. public:

.. enum {value = 1};

..};


这将为您提供编译时多态性我认为您

在您的原始帖子中寻找。


希望这会有所帮助,

-shez-



Please take a look at the following code:

template <typename T, typename Enable = void>
class A
{
public:
enum { value = 0 };
};

template <typename T>
class A<T, typename T::Enable>
{
public:
enum { value = 1 };
};

class B
{
public:
typedef void Enable;
};

class C
{
};

int main(int argc, char *argv[])
{
int b = A<B>::value; // should be 1
int c = A<C>::value; // should be 0
return 0;
}

The goal here was to create a class template called A in a way that
A<T>::value is 1 if T::Enable exists, and 0 otherwise. I''ve tried this
on MSVC++ 7.1, and it actually works, but only if T::Enable is exactly
the same type as the default value of the Enable template argument of
A. For example, if I change the typedef in B to
typedef int Enable; // int instead of void
then the value of variable b in main will be 0.

I''d like to know why''s that. I thought that the specialization would be
a better match for all types where T::Enable exists, regardless of what
type it actually means. And I can''t really see the connection with the
second template argument.

Imre

解决方案


Imre wrote:

Please take a look at the following code:

template <typename T, typename Enable = void>
class A
{
public:
enum { value = 0 };
};

template <typename T>
class A<T, typename T::Enable>
{
public:
enum { value = 1 };
};

class B
{
public:
typedef void Enable;
};

class C
{
};

int main(int argc, char *argv[])
{
int b = A<B>::value; // should be 1
int c = A<C>::value; // should be 0
return 0;
}

The goal here was to create a class template called A in a way that
A<T>::value is 1 if T::Enable exists, and 0 otherwise. I''ve tried this on MSVC++ 7.1, and it actually works, but only if T::Enable is exactly the same type as the default value of the Enable template argument of
A. For example, if I change the typedef in B to
typedef int Enable; // int instead of void
then the value of variable b in main will be 0.

I''d like to know why''s that. I thought that the specialization would be a better match for all types where T::Enable exists, regardless of what type it actually means. And I can''t really see the connection with the second template argument.

Imre



I''m guessing what you really want is a "trait":

.. #include <iostream>
..
.. template <typename T>
.. class Trait
.. {
.. public:
.. enum { ENABLE = 0 };
.. };

This defines a trait, by default it is zero. Now you can define your
''A'' class like this:

.. template <typename T, typename T2 = Trait<T> >
.. class A
.. {
.. public:
.. enum { value = T2::ENABLE };
.. };

This gets ''value'' from the ''ENABLE'' enum in your Trait class (which is
zero by default). Now you can create your other classes:

.. class B { };
.. class C { };

Now, specialise Trait<T> so that ''ENABLE'' is set to one for class ''B'':

.. template <>
.. class Trait<B>
.. {
.. public:
.. enum { ENABLE = 1 };
.. };

This means that ''B'' is now enabled for whatever you want to do in ''A''.

.. int main(int argc, char *argv[])
.. {
.. int b = A<B>::value; // should be 1
.. int c = A<C>::value; // should be 0
..
.. std::cout << b << " " << c << std::endl;
..
.. return 0;
.. }
This should print out "1 0" (as expected).

Hope this helps,
-shez-


I think it is possible that you are confusing default template
parameters with with partial template specialization.

If you look at your code above, neither of the lines:

int b = A<B>::value; // should be 1
int c = A<C>::value; // should be 0
explicitly supplies the ''Enable'' parameter of your original template.

For that reason, you have implicitly written:

int b = A<B, void>::value;
int c = A<C, void>::value;

In other words, in both cases, your second template parameter is of
type void.

This means that when the compiler is deciding whether or not to use the
partial template specialization:
template <typename T>
class A<T, typename T::Enable>
{
public:
enum { value = 1 };
};
that T::Enable must be of type void in order to the specialization to
be chosen.

If you write:

class B
{
public:
typedef int Enable;
};

then the implicitly written line:

int b = A<B, void>::value;

does not use the partial template specialization:
template <typename T>
class A<T, typename T::Enable>
{
public:
enum { value = 1 };
};



because T::Enable (really B::Enable) is of type int, and the second
parameter of A<B, void> is of type void. In other words, since void is
the type of the second template parameter, a T::Enable of type int
cannot be applied, and the specialization cannot be chosen because of
the type conflict.

I hope this helps! =)

Michael Loritsch



Shezan Baig wrote:

This defines a trait, by default it is zero. Now you can define your
''A'' class like this:

. template <typename T, typename T2 = Trait<T> >
. class A
. {
. public:
. enum { value = T2::ENABLE };
. };



Also, if you want to have a separate specialisation for ENABLE = 1 (as
in your original post), you can do this:

.. template <typename T,
.. typename T2 = Trait<T>,
.. int ENABLE = T2::ENABLE >
.. class A
.. {
.. public:
.. enum { value = 0 };
.. };
..
.. template <typename T, typename T2>
.. class A<T, T2, 1>
.. {
.. public:
.. enum { value = 1 };
.. };

This will give you the compile-time polymorphism I think you were
looking for in your original post.

Hope this helps,
-shez-


这篇关于模板参数匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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