如何“模式匹配”一个模板?
通常在模板中,您想要了解整个类型,但在我的情况下,我需要了解更多,并且想要“分解”类型。举个例子:
template <typename Collection<typename T> >
T get_front(Collection const& c)
{
return c.front();
}
我怎样才能实现这一目标?注意:我需要它自动推导类型,而不是传递类似
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
编辑:C++0x的方法可以在最后找到。
编辑2:我很愚蠢,并且比所有这些特征内容更短的方式 C++98/03 方式可以在答案的末尾找到。
如果您希望您的函数适用于任何任意标准库容器,您需要拿出一些模板枪。
问题是,不同的容器采用不同数量的模板参数。例如,
std::vector
、std::deque
和std::list
取 2:基础项类型T 和分配器类型
Alloc
。另一方面,std::set
和std::map
分别采用 3 和 4:两者都有键类型K
,map 采用另一个值类型V
,然后两者都采用比较器Compare
类型和分配器类型Alloc
。您可以在此处获取标准库提供的所有容器类型的概述。现在,介绍模板枪。我们将使用部分专门化的特征元结构来获取底层项目类型。 (出于纯粹的偏好,我使用
class
而不是typename
。)现在准备工作已经完成,接下来是
get_front
函数!唷!就是这样!完整的示例可以在 Ideone 上查看。当然,可以进一步细化,直到返回映射到 std::map 中的键的实际值,或者使用容器特定的访问函数,但我是只是有点懒得这么做。 :P
编辑
一种更简单的 C++0x 方法是使用新的尾随返回类型函数语法,可以在 在 Ideone 上。
编辑2
好吧,我不知道为什么,但在编写这个答案时我完全没有想到嵌套的 typedef 。我将保留详细的方式作为匹配模板的特征类/模式的参考。 这就是这样做的方法,它基本上与我对特征类所做的相同,但最终不那么冗长。
Edit: A C++0x way can be found at the end.
Edit 2: I'm stupid, and a way shorter C++98/03 way than all this traits stuff can be found at the end of the answer.
If you want your function to work for any arbitary standard library container, you need to pull out some Template Guns.
The thing is, that the different container take a different amount of template parameters.
std::vector
,std::deque
andstd::list
for example take 2: the underlying item typeT
and the allocator typeAlloc
.std::set
andstd::map
on the other hand take 3 and 4 respectively: both have the key typeK
, map takes another value typeV
, then both take a comparatorCompare
type and the allocator typeAlloc
. You can get an overview of all container types supplied by the standard library for example here.Now, for the Template Guns. We will be using a partially specialized traits metastruct to get the underlying item type. (I use
class
instead oftypename
out of pure preference.)Now that the preparation is done, on to the
get_front
function!Phew! And that's it! A full example can be seen on Ideone. Of course it would be possible to refine that even further, to the point of returning the actual value that is mapped to a key in a
std::map
, or use container specific access functions, but I was just a bit too lazy to do that. :PEdit
A way easier C++0x way is using the new trailing-return-type function syntax, of which an example can be found here on Ideone.
Edit 2
Well, I don't know why, but I totally didn't think of the nested
typedef
s when writing this answer. I'll let the verbose way stay as a reference for traits classes / pattern matching a template. This is the way to do it, it is basically the same I did with the traits classes, but ultimately less verbose.如果您知道它不是关联容器,则可以这样做。
You could do this if you know it's not an associative container.
我假设您想要
Collection
和T
作为模板参数。为此,只需输入构造
template <类型名称> class Collection
告诉编译器Collection
本身就是一个带有一个参数的模板。编辑:
正如 Xeo 所指出的,
vector
采用两个模板参数,并且您的模板需要反映这一点, IEI'm assuming you want both
Collection
andT
as template parameters. To do that simply typeThe construct
template < typename > class Collection
tells the compiler thatCollection
is a template itself with one parameter.Edit:
As pointed out be Xeo,
vector
takes two template parameters, and your templates need to reflect that, i.e.鉴于
Collection
是提前知道的,我认为你想要的是:唯一改变的部分是
T
是什么,它总是在中集合
(内容,而不是容器),因此您不必将其作为模板的一部分。如果容器发生变化,使用 c.front() 可能会很危险。您需要验证集合类型是否具有不带参数并返回
T
的方法front
。编辑:
如果您确实需要模板
Collection
,那么这更像是:如果可以的话,我会避免通用的东西,也许专门为您知道将使用的集合的功能,或特定类别的类(如果可能)。
Seeing as
Collection<T>
is known ahead of time, I think what you want is:The only part that's changing is what
T
is, it's always in aCollection
(contents, not the container) so you don't have put that as part of the template.If the container was changing, using
c.front()
could be dangerous. You would need to verify that the collection type had a methodfront
that took no parameters and return aT
.Edit:
If you do need to template
Collection
, then that's more like:I would avoid something that generic if you can, perhaps specializing the function for collections you know will be used, or to a particular class of classes (if possible).