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

时间:2009-06-02 15:27:01

标签: c++ templates overloading

预先警告:这个问题似乎比实际情况更明显。

我想编写一个可以接受任何具体类或模板类作为模板参数的模板。这似乎没用,因为不知道传入的T是否是模板化的,你将不知道如何使用它。我想要这个的原因是我可以声明一个没有定义的通用模板,然后用户专门化。因为用户专注于它,所以他们总是知道他们正在处理的类型。但是,如果没有首先声明模板,用户就无法专门化模板。

你可以这样做:

template<class T>
class myclass;

但如果传入模板化的T,那将无效,例如myclass<std::vector>将无效。那么我们试试这个:

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的参数本身就是模板?

3 个答案:

答案 0 :(得分:3)

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”) 。我甚至不确定可变参数模板是否会影响模板模板参数(尽管有趣的问题)。

答案 1 :(得分:1)

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

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

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 ++将始终期望重载,而不是模板特化。

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

答案 2 :(得分:0)

template <class T> class myclass;

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

这是你想要的吗?