带有模板参数的模板中的默认值(C ++) [英] Default values in templates with template arguments ( C++ )

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

问题描述

假设我有一个模板(称为ExampleTemplate),它接受两个参数:一个容器类型(例如list,vector)和一个包含类型(例如float,bool等)。由于容器实际上是模板,所以此模板具有模板参数。这是我不得不写的:

  #include< vector> 
#include< list>

using namespace std;

template< template< class,class>类C,类型名T>
class ExampleTemplate {
C< T,allocator< T> >项目;
public:
....
};

main()
{
ExampleTemplate< list,int>一个;
ExampleTemplate< vector,float> b;
}

你可能会问什么是allocator。好吧,最初,我尝试了明显的事情...

  template< template< class>类C,类型名T> 
class ExampleTemplate {
C< T>项目;
};

...但我不幸发现allocator的默认参数...

 向量< T,Alloc> 
list< T,Alloc>
etc

...必须在模板声明中明确保留。
这个,正如你所看到的,使代码更丑陋,并强迫我重现模板参数(在这种情况下,分配器)的默认值。



< 问题不是容器的具体问题 - 它是关于带有模板参数的模板中的默认值,上面仅是一个示例。根据STL容器有一个:: value_type的知识的答案不是我的后面。考虑通用问题:如果我需要在模板ExampleTemplate中使用模板参数C,那么在ExampleTemplate的主体中,当我使用它时,我必须重现C的默认参数吗?如果我到,不会引入不必要的重复和其他问题(在这种情况下,其中C是STL容器,可移植性问题 - 例如allocator)?

解决方案

也许你更喜欢这个:

  include< vector> 
#include< list>

using namespace std;

template< class Container>
class ForExamplePurposes {
typedef typename Container :: value_type T;
容器项目;
public:
};

int main()
{
ForExamplePurposes& list< int> >一个;
ForExamplePurposes& vector< float> > b;
}

这使用static 鸭式打字。它也有点更灵活,因为它不强制Container类型支持STL的Allocator概念。






类型特征成语可以为您提供一个途径:

  #include< vector> 
#include< list>

using namespace std;

struct MyFunkyContainer
{
typedef int funky_type;
// ...定制容器声明的其余部分
};

//一般情况假定STL兼容的容器
template< class Container>
struct ValueTypeOf
{
typedef typename Container :: value_type type;
};

// MyFunkyContainer的专用化
模板<>
struct ValueTypeOf< MyFunkyContainer>
{
typedef MyFunkyContainer :: funky_type type;
};


模板< class Container>
class ForExamplePurposes {
typedef typename ValueTypeOf< Container> :: type T;
容器项目;
public:
};

int main()
{
ForExamplePurposes& list< int> >一个;
ForExamplePurposes& vector< float> > b;
ForExamplePurposes& MyFunkyContainer> C;
}

有人想使用 ForExamplePurposes 与非STL兼容的容器需要专门化 ValueTypeOf traits类。


Assume I have a template (called ExampleTemplate) that takes two arguments: a container type (e.g. list, vector) and a contained type (e.g. float, bool, etc). Since containers are in fact templates, this template has a template param. This is what I had to write:

#include <vector>
#include <list>

using namespace std;

template < template <class,class> class C, typename T>
class ExampleTemplate {
    C<T,allocator<T> > items;
public:
    ....
};

main()
{
    ExampleTemplate<list,int> a;
    ExampleTemplate<vector,float> b;
}

You may ask what is the "allocator" thing about. Well, Initially, I tried the obvious thing...

template < template <class> class C, typename T>
class ExampleTemplate {
    C<T> items;
};

...but I unfortunately found out that the default argument of the allocator...

   vector<T, Alloc>
   list<T, Alloc>
   etc

...had to be explicitely "reserved" in the template declaration. This, as you can see, makes the code uglier, and forces me to reproduce the default values of the template arguments (in this case, the allocator).

Which is BAD.

EDIT: The question is not about the specific problem of containers - it is about "Default values in templates with template arguments", and the above is just an example. Answers depending on the knowledge that STL containers have a "::value_type" are not what I am after. Think of the generic problem: if I need to use a template argument C in a template ExampleTemplate, then in the body of ExampleTemplate, do I have to reproduce the default arguments of C when I use it? If I have to, doesn't that introduce unnecessary repetition and other problems (in this case, where C is an STL container, portability issues - e.g. "allocator" )?

解决方案

Perhaps you'd prefer this:

#include <vector>
#include <list>

using namespace std;

template <class Container>
class ForExamplePurposes {
    typedef typename Container::value_type T;
    Container items;
public:
};

int main()
{
    ForExamplePurposes< list<int> > a;
    ForExamplePurposes< vector<float> > b;
}

This uses "static duck typing". It is also a bit more flexible as it doesn't force the Container type to support STL's Allocator concept.


Perhaps using the type traits idiom can give you a way out:

#include <vector>
#include <list>

using namespace std;

struct MyFunkyContainer
{
    typedef int funky_type;
    // ... rest of custom container declaration
};

// General case assumes STL-compatible container
template <class Container>
struct ValueTypeOf
{
    typedef typename Container::value_type type;
};

// Specialization for MyFunkyContainer
template <>
struct ValueTypeOf<MyFunkyContainer>
{
    typedef MyFunkyContainer::funky_type type;
};


template <class Container>
class ForExamplePurposes {
    typedef typename ValueTypeOf<Container>::type T;
    Container items;
public:
};

int main()
{
    ForExamplePurposes< list<int> > a;
    ForExamplePurposes< vector<float> > b;
    ForExamplePurposes< MyFunkyContainer > c;
}

Someone who wants to use ForExamplePurposes with a non-STL-compliant container would need to specialize the ValueTypeOf traits class.

这篇关于带有模板参数的模板中的默认值(C ++)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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