如何编写一个接受每个类和类模板的 C++ 模板?

Posted

技术标签:

【中文标题】如何编写一个接受每个类和类模板的 C++ 模板?【英文标题】:How to write a C++ template that accepts every class and class template? 【发布时间】:2009-06-02 15:27:01 【问题描述】:

预先警告:这个问题似乎比实际要明显得多。

我想编写一个可以接受任何具体类或模板类作为模板参数的模板。这可能看起来没用,因为如果不知道传入的 T 是否是模板化的,您将不知道如何使用它。我想要这个的原因是我可以声明一个没有定义的通用模板,然后用户可以专门化。因为用户专门研究它,所以他们总是知道他们正在处理的类型。但是用户不能在没有先声明模板的情况下对其进行专门化。

你可以这样做:

template<class T>
class myclass;

但是如果你传入一个模板化的 T 就行不通了,例如myclass&lt;std::vector&gt; 就行不通了。那么我们试试这个:

template<class T>
class myclass;

template<template<class> T>
class myclass;

这可能是正确的方法,但它不会按原样工作,因为类模板不能重载。所以我们把它切换成函数模板,可以是:

template<class T>
void myfunc();

template<template<class> T>
void myfunc();

太好了,所以我们完成了吗?好吧,模板模板参数可能有不同数量的参数,所以我们也需要考虑到这一点。

template<class T>
void myfunc();

template<template<class> T>
void myfunc();

template<template<class, class> T>
void myfunc();

template<template<class, class, class> T>
void myfunc();

// etc.

丑陋,但Boost Preprocessor Library 可以为我们生成此代码(并且在 C++0x 中将添加对可变参数模板的支持,因此这种丑陋只是暂时的)。但是我们还是忘记了一个案子!如果 T 的一个参数不是一个类,而是一个常量整数怎么办。让我们尝试支持它:

template<class T>
void myfunc();

template<template<class> T>
void myfunc();

template<template<class, class> T>
void myfunc();

template<template<class, class, class> T>
void myfunc();

// etc.

template<template<class> T>
void myfunc();

template<template<class, int> T>
void myfunc();

template<template<int, class> T>
void myfunc();

template<template<int, class, class> T>
void myfunc();

template<template<class, int, class> T>
void myfunc();

template<template<class, class, int> T>
void myfunc();

// etc.

哦哦。鉴于任何常量类型都可以传入模板,以任意数量与类参数混合,KABLOOEY 组合爆炸。只是为了让事情变得更加困难,如果 T 的任何参数本身就是模板怎么办?

【问题讨论】:

我会回到绘图板并明确定义需求。你想达到什么目标?混合模板和类是否有意义(注意 std::vector 是一个类,而不是模板)。你真正想解决什么问题? 【参考方案1】:

boost::mpl 做了这样的事情(这是他们对binding an argument 的想法)。但是,您必须做出很多假设才能使其发挥作用,例如使用;

template <class T> foo  ; typedef foo< int_<4> > my_foo_4;

而不是

template <int T> foo  ; typedef foo<4> my_foo_4;

不必为所有 int、char、bool 等组合提供重载。

我想不出比 boost::mpl 方法更有效的方法,而且总的来说,我认为任何方法都会遇到很多问题;类模板不是类型,它不能真正嵌入到类型系统中(boost::mpl 将其视为创建新类型的函数;更一般地说,它用于创建“MetaFunction”) .我什至不确定可变参数模板是否会影响模板模板参数(虽然很有趣)。

【讨论】:

托德,他们会的。在 C++1x 中,您将能够执行 template struct Take;模板 中获取它们的参数 使用 int_ 是我想到的一个想法,但我害怕走那条路;)我必须对模板模板参数和插入参数做同样的事情进入那些,这比我想象的要多一点。我想我只需要尝试一下,看看会发生什么。 MPL 允许轻松地使用 lambda:传递 vector<_1> 作为类型,然后使用 typename mpl::apply::type (T 是模板参数),你得到矢量【参考方案2】:

解决方案是:使用函数重载而不是模板特化!编译时间会更好,约束消失了……

请记住,任何模板都被视为在最近的全局范围内实例化,之后使用它们。这意味着这将起作用:

template <class T>
int f(const T& t)

  return g(t);
 

int g(int a)

  return a+1;


int main()

   return f(5);

如您所见,即使函数g 是在f 之后定义的,它仍然有效。这意味着您可以定义使用该函数的任何模板,只要用户在使用模板之前定义了该函数,就可以了,C++会找到它。

还请记住,函数不存在模板特化!如果存在许多同名的函数,C++ 将总是期望重载,而不是模板特化。

简而言之,最好的解决方案是:就像函数存在一样使用它,并期望用户在使用模板之前定义函数。

【讨论】:

这个问题已经使用了重载——答案没有解决这个问题。据我了解,他希望能够调用 f()、f()、f<:bind>() (!) 等。 我不同意……他想为用户定义一个模板来专门化它。然后,OP 建议预定义函数模板。但是你不能专门化函数模板。另外,如果 OP 想要定义这个函数,这是在他的代码中使用它。否则,OP 应提供有关如何使用该功能的更多详细信息。【参考方案3】:
template <class T> class myclass;

template <> class myclass<int>;
template <> class myclass<std::vector<int>>;
template <> class myclass<std::vector<std::vector<int> > >;

这是你想要的吗?

【讨论】:

不。我希望能够在 std::vector 上专门化 myclass 而无需实际给 std::vector 一个类型。为此,您需要模板模板参数。

以上是关于如何编写一个接受每个类和类模板的 C++ 模板?的主要内容,如果未能解决你的问题,请参考以下文章

7群体类和群体数据的组织-1.函数模板和类模板

C++学习笔记:高级编程:模板,预处理器,信号处理,多线程,Web编程

C++模板第一篇:函数模板和类模板

C++模板详解

C++模板

C++ 模板详解(转)