如何从模板函数返回模板类?

时间:2010-05-25 18:55:08

标签: c++ templates

如何启动会使最后一个注释行编译的内容?我如何更改此代码以使其工作?

#include<iostream>

using namespace std;

template <int x>
class someclass{
 public:
  int size;
  int intarr[x];
  someclass():size(x){}
};

template<int x, int y>
int somefunc(someclass<x> A, someclass<y> B){
 return ( A.size > B.size ? A.size : B.size); 
}

template<int x, int y, int z>
someclass<x> anotherfunc(someclass<y> A, someclass<z> B){
 return ( A.size > B.size ? A : B); 
}

int main(){

 someclass<5> A;
 someclass<10> B;
 cout << "SIZE = " << somefunc(A,B) << endl;
 //cout << "SIZE = " << (anotherfunc(A,B)).size << endl; //THIS DOES NOT COMPILE
 return 0;
}

2 个答案:

答案 0 :(得分:4)

如何知道函数外部x是什么? (它无法查看正文,因为在它看起来功能的主体取决于x得到的值!)。此外,你不能写?:,因为你的两个分支都产生完全不相关的类型,这些类型不可能达到一个普通类型。但是该运算符需要为它所评估的两个分支都有一个公共类型。

然后另一个帖子已经详细阐述了size不是编译时常量的另一个问题。

我认为这应该有效:

template<int y, int z>
someclass<sizeof (char[+(y >= z)]) * y> anotherfunc(someclass<y> A, someclass<z> B){
 return A; 
}

template<int y, int z>
someclass<sizeof (char[+(y < z)]) * z> anotherfunc(someclass<y> A, someclass<z> B){
 return B; 
}

现在调用它时,参数推导出yz,然后将参数替换为返回类型。 sizeof(char[1 or 0])将测试yz是否更大。在将其计算为sizeof(char[1])(产生1)的相应模板中,我们将乘以更大(或相等)的值。如果相应的模板产生sizeof(char[0]),则这是一个演绎失败(数组不能为零大小!),并且模板不会通过重载决策选择(称为 SFINAE ) 。

一元+10作为int而不是truefalse,这可能会导致某些编译器出现编译器警告。


enable_if还有“干净”的方式。它没有做一些可怕的sizeof技巧,而是使用一般建立的enable_if模式。 Boost有一个实现它

template<int y, int z>
typename boost::enable_if_c<(y >= z), someclass<y> >::type 
anotherfunc(someclass<y> A, someclass<z> B){
 return A; 
}

template<int y, int z>
typename boost::enable_if_c<(y < z), someclass<z> >::type 
anotherfunc(someclass<y> A, someclass<z> B){
 return B; 
}

这可能乍一看看起来更嘈杂,但应该更容易理解,并且更快地跟随已经习惯enable_if的人(boost的实现的_c变体接受普通的布尔值,如上文)。

答案 1 :(得分:3)

请记住,在C ++中,一切都是在编译时确定的。在anotherfunc中,直到运行时才知道是否返回“y-typed”或“z-typed”类。如果要从函数返回模板类,则需要知道要返回的内容。

你可以通过重载中间类的强制转换操作符来获取一些技巧,以获得看起来像在返回类型上重载的东西,但这实际上是在滥用语言(并且你仍然需要在编译时知道返回类型!)