带有模板参数的模板中的默认值(C++)

tts*_*ras 27 c++ templates

假设我有一个模板(称为ExampleTemplate),它带有两个参数:容器类型(例如list,vector)和包含的类型(例如float,bool等).由于容器实际上是模板,因此该模板具有模板参数.这是我必须写的:

#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;
}
Run Code Online (Sandbox Code Playgroud)

你可能会问什么是"分配器"的事情.好吧,最初,我尝试了显而易见的事情......

template < template <class> class C, typename T>
class ExampleTemplate {
    C<T> items;
};
Run Code Online (Sandbox Code Playgroud)

...但遗憾的是我发现了分配器的默认参数......

   vector<T, Alloc>
   list<T, Alloc>
   etc
Run Code Online (Sandbox Code Playgroud)

...必须在模板声明中明确地"保留".正如您所看到的,这会使代码变得更加丑陋,并迫使我重现模板参数的默认值(在本例中为分配器).

哪个是坏的.

编辑:问题不是关于容器的具体问题 - 它是关于"模板参数模板中的默认值",以上只是一个例子.答案取决于STL容器具有":: value_type"的知识不是我所追求的.想想一般问题:如果我需要在模板ExampleTemplate中使用模板参数C,那么在ExampleTemplate的主体中,我是否必须在使用它时重现C的默认参数?如果必须,那不会引入不必要的重复和其他问题(在这种情况下,C是STL容器,可移植性问题 - 例如"allocator")?

Emi*_*ier 14

也许你更喜欢这个:

#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;
}
Run Code Online (Sandbox Code Playgroud)

这使用"静态鸭子打字 ".它也更灵活,因为它不会强制Container类型支持STL的Allocator概念.


也许使用类型特征成语可以给你一个出路:

#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;
}
Run Code Online (Sandbox Code Playgroud)

想要ForExamplePurposes与非STL兼容容器一起使用的人需要专门化ValueTypeOftraits类.


Mat*_* M. 5

我建议创建适配器.

应该使用类所需的确切个性化级别创建您的类:

template <template <class> C, template T>
class Example
{
  typedef T Type;
  typedef C<T> Container;
};
Run Code Online (Sandbox Code Playgroud)

编辑:尝试提供更多是很好的,但注定要失败,看看各种扩展:

  • std::vector<T>: std::vector<T, std::allocator<T>>
  • std::stack<T>: std::stack<T, std::deque<T>>
  • std::set<T>: std::set<T, std::less<T>, std::allocator<T>>

第二个是适配器,所以不采用分配器,第三个没有相同的arity.因此,您需要将责任放在用户身上.

如果用户希望使用不符合表达方式的类型,那么对他来说最简单的方法是提供(本地)适配器:

template <typename T>
using Vector = std::vector<T>; // C++0x

Example<Vector, bool> example;
Run Code Online (Sandbox Code Playgroud)

我想知道有关使用参数包(可变参数模板)在这里......我不知道,如果声明Ctemplate <class...> C会做的伎俩,或者如果编译器需要一个可变参数类,那么.