WEB开发网
开发学院软件开发VC 模板友元化 阅读

模板友元化

 2007-03-16 21:57:45 来源:WEB开发网   
核心提示: 因为,问题——大多数编译器上不能处理例1――产生于在另一个命名空间中明确地声明了某个函数模板的特化,模板友元化(6),(喝倒彩三声?:)微软的Visual C++ 6.0 编译器甚至不能处理最简单的情况,两种错误的答案(Non-Workarounds)当这个问题在U

因为,问题——大多数编译器上不能处理例1――产生于在另一个命名空间中明确地声明了某个函数模板的特化。(喝倒彩三声?:)微软的Visual C++ 6.0 编译器甚至不能处理最简单的情况。

两种错误的答案(Non-Workarounds)

当这个问题在Usenet被提出时,一些人的回复中建议用一个using声明(或者等价地using指示),去掉友元声明的作用域限定:

namespace boost {
 template<typename T> void checked_delete( T* x ) {
  // ... 其它代码 ...
  delete x;
}
}
using boost::checked_delete;
class Test {
 ~Test() { }
 // 没有模板特化!
 friend void checked_delete( Test* x );
};   

上边的友元声明又落入了#4的形式:"4.否则,友元的名字必须不被冠以作用域修饰,而是声明为一个常规函数(非模板)。"这实际上是在全局命名空间中声明了一个新的常规非模板函数::checked_delete(Test*)。

如果你试试上边的代码,上述数编译中的大多数器都会拒绝它,并提示checked_delete()没有被定义;而且它们全部都会拒绝让你在boost::checked_delete()模板中以友元的身份去调用类的私有成员。

最后,一位专家建议把它稍稍改一下——使用"using"也是用模板语法"<>":

namespace boost {
 template<typename T> void checked_delete( T* x ) {
  // ... 其它代码 ...
  delete x;
}
}
using boost::checked_delete;
class Test {
 ~Test() { }
 friend void checked_delete<>( Test* x ); //合法么?
};   

上边不是合法的C++代码——C++标准没有明确指出这是合法的。在标准委员会中,曾经有一过一次公开的讨论——以决定该用法是否合法,存在一个观点认为它应该是非法的,因为事实上所有我测试过的当前编译器都拒绝它。为什么人们认为它不能是合法的呢?为了保持一致性,因为using的存在是为了令名字使用起来更加容易——调用函数/在变量或参数声明中使用类型名。声明有所不同的是:正如你必须在模板的原始作用域中声明该模板的一个特化一样,(你不能在另一个命名空间中通过"using"来达到这一目的),你只能将一个模板的特化声明为——冠以该模板作用域的——友元(而不能通过"using"来做到这一点)。

总结

为了友元化一个函数模板的特化,应该选择如下2种语法之一:

 // 来自例1
 friend void boost::checked_delete ( Test* x );
 // 来自例2:增加<>或<Test>
 friend void boost::checked_delete<>( Test* x );   

本文演示了——不像例2所示,写上"<>"或"<Test>"的代码所产生的——严重的移植性问题。

方针:说明白你到底想要什么。(Guideline:Say what you mean, be explicit.)

当你友元化一个函数模板的特化时,应该总是清楚地冠以模板的语法,至少加上"<>"。例如:

namespace boost {
 template<typename T> void checked_delete( T* x );
}
class Test {
 friend void boost::checked_delete ( Test* x ); // 不好
 friend void boost::checked_delete<>( Test* x ); // 好
};   

如果你的编译器不支持这两种声明友元的合法语法的话,你就要把必要的函数声明为公共的了――不过,应该加上一条注释以说明原因,并提醒自己一旦编译器升级了的话,便应尝试将这些函数声明改回成私有的。

承谢

感谢John Potter对本文草稿的审校。

注释

[1] 有其它的实现方式,但却笨拙。例如:可以在命名空间boost中创建一个代理类并对其友元化。

上一页  1 2 3 4 5 6 

Tags:模板 元化

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接