C++ 具有模板参数(C+;+;)的模板中的默认值
假设我有一个模板(称为ExampleTemplate),它接受两个参数:容器类型(例如list、vector)和包含类型(例如float、bool等)。因为容器实际上是模板,所以此模板有一个模板参数。这就是我要写的:C++ 具有模板参数(C+;+;)的模板中的默认值,c++,templates,C++,Templates,假设我有一个模板(称为ExampleTemplate),它接受两个参数:容器类型(例如list、vector)和包含类型(例如float、bool等)。因为容器实际上是模板,所以此模板有一个模板参数。这就是我要写的: #include <vector> #include <list> using namespace std; template < template <class,class> class C, typename T> class
#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;
}
#包括
#包括
使用名称空间std;
模板<模板类别C,类型名T>
类示例模板{
C项目;
公众:
....
};
main()
{
例如模板a;
示例模板b;
}
你可能会问“分配器”是关于什么的。嗯,一开始,我尝试了一件显而易见的事情
template < template <class> class C, typename T>
class ExampleTemplate {
C<T> items;
};
template
类示例模板{
C项目;
};
…但我不幸发现分配器的默认参数
vector<T, Alloc>
list<T, Alloc>
etc
向量
列表
等
…必须在模板声明中明确“保留”。
如您所见,这使得代码更加丑陋,并迫使我重新生成模板参数的默认值(在本例中为分配器)
这很糟糕
编辑:问题不是关于容器的具体问题,而是关于“带有模板参数的模板中的默认值”,以上只是一个示例。答案取决于STL容器具有“::value\u type”的知识,而不是我想要的。考虑一个一般性问题:如果我需要在模板ExampleTemplate中使用模板参数C,那么在ExampleTemplate的主体中,当我使用它时是否必须复制C的默认参数?如果必须这样做,这是否会带来不必要的重复和其他问题(在本例中,C是STL容器,可移植性问题-例如“分配器”)?也许您更喜欢这样:
#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;
}
#包括
#包括
使用名称空间std;
模板
类示例目的{
typedef typename容器::value_type T;
货柜物品;
公众:
};
int main()
{
例如,目的a;
例如b;
}
它使用“静态”。它也更加灵活,因为它不强制容器类型支持STL的分配器概念
也许使用这个成语可以给你一条出路:
#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;
}
#包括
#包括
使用名称空间std;
结构MyFunkyContainer
{
typedef int funky_类型;
//…自定义容器声明的其余部分
};
//一般情况下,假定STL兼容容器
模板
结构值类型
{
typedef typename容器::值\类型类型;
};
//MyFunkyContainer的专门化
模板
结构值类型
{
typedef MyFunkyContainer::funky_类型;
};
模板
类示例目的{
typedef typename ValueTypeOf::type T;
货柜物品;
公众:
};
int main()
{
例如,目的a;
例如b;
例如,目的c;
}
例如,想要将
用于不符合STL的容器的人需要专门化ValueTypeOf
traits类。以下代码将允许您执行您要求的操作。当然,这不适用于标准容器,因为它必须已经是传递到模板中的模板类的一部分
/* Allows you to create template classes that allow users to specify only some
* of the default parameters, and some not.
*
* Example:
* template <typename A = use_default, typename B = use_default>
* class foo
* {
* typedef use_default_param<A, int> a_type;
* typedef use_default_param<B, double> b_type;
* ...
* };
*
* foo<use_default, bool> x;
* foo<char, use_default> y;
*/
struct use_default;
template<class param, class default_type>
struct default_param
{
typedef param type;
};
template<class default_type>
struct default_param<use_default, default_type>
{
typedef default_type type;
};
/*允许您创建允许用户仅指定某些模板类的模板类
*默认参数的一部分,有些不是。
*
*例如:
*模板
*福班
* {
*typedef使用默认参数a_类型;
*typedef使用默认参数b_类型;
* ...
* };
*
*富x;
*福伊;
*/
结构使用默认值;
模板
结构默认参数
{
typedef参数类型;
};
模板
结构默认参数
{
typedef默认_类型;
};
但我真的认为这不是你想要的。您对容器所做的操作不太可能适用于任意容器,因为其中许多容器都会遇到多个默认参数的问题,这些默认参数的默认类型不明显。我建议创建适配器
创建的类应具有该类所需的确切个性化级别:
template <template <class> C, template T>
class Example
{
typedef T Type;
typedef C<T> Container;
};
模板
课例
{
T型;
C型容器;
};
编辑:尝试提供更多是好的,但注定会失败,请查看各种扩展:
std::vector
:std::vector
std::stack
:std::stack
std::set
:std::set
第二个是适配器,因此不接受分配器,第三个没有相同的算术。因此,您需要将责任推给用户
如果用户希望将其与不尊重所表示的算术的类型一起使用,则最简单的方法是(本地)提供一个适配器:
template <typename T>
using Vector = std::vector<T>; // C++0x
Example<Vector, bool> example;
模板
使用Vector=std::Vector;//C++0x
实例;
我想知道参数包(可变模板)在这里的使用。。。我不知道将C
声明为template C
是否会起作用,或者编译器是否需要一个可变类。我认为,需要复制所有模板参数,即使是默认参数。注意,该标准本身不使用集装箱适配器的模板参数,而是更喜欢使用常规模板参数:
template < class T , class Container = deque <T > > class queue { ... };
template < class T , class Container = vector <T>, class Compare = less < typename Container :: value_type > > class priority_queue { ... };
templateclass队列{…};
模板>类优先级\u队列{…};
如果希望能够以常规方式使用模板参数,则必须提供完整的模板签名,包括默认参数
template <typename T, template <class U, class V = allocator<U> > class C>
class ExampleTemplate {
C<T> items;
public:
....
};
模板
类示例模板{
C项目;
公众:
....
};
如果要处理来自STL的其他容器,可以委托contai
// Other specialization failed. Instantiate a std::vector.
template <typename T, typename C>
struct make_container_
{
typedef std::vector<T> result;
};
// STL containers
template <typename T, template <class U, class V = allocator<U> > class C>
struct make_container_<T,C>
{
typedef C<T> result;
};
// Other specializations
...
template <typename T, typename C>
class ExampleTemplate {
make_container_<T,C>::result items;
public:
....
};
// this is simply the replacement for a normal type:
// it takes a type T, and possibly replaces it with ReplaceByType
template<typename T, typename ReplaceWhatType, typename ReplaceByType>
struct replace_type
{
using type = std::conditional_t<std::is_same<T, ReplaceWhatType>::value, ReplaceByType, T>;
};
// this sets up the recursion, such that replacement also happens
// in contained nested types
// example: in "std::vector<T, allocator<T> >", both T's are replaced
template<template<typename ...> class C, typename ... Args, typename ReplaceWhatType, typename ReplaceByType>
struct replace_type<C<Args ...>, ReplaceWhatType, ReplaceByType>
{
using type = C<typename replace_type<Args, ReplaceWhatType, ReplaceByType>::type ...>;
};
// an alias for convenience
template<typename ... Args>
using replace_type_t = typename replace_type<Args ...>::type;
struct DummyType {};
template <typename C, typename T>
struct ExampleTemplate
{
replace_type_t<C, DummyType, T> items;
};
int main()
{
ExampleTemplate<std::vector<DummyType>, float> a;
a.items.push_back(1.0);
//a.items.push_back("Hello"); // prints an error message which shows that DummyType is replaced correctly
ExampleTemplate<std::list<DummyType>, float> b;
b.items.push_back(1.0);
//b.items.push_back("Hello"); // prints an error message which shows that DummyType is replaced correctly
ExampleTemplate<std::map<int, DummyType>, float> c;
c.items[0]=1.0;
//c.items[0]="Hello"; // prints an error message which shows that DummyType is replaced correctly
}