现在的位置: 首页 > 综合 > 正文

STL杂记(3)

2012年08月27日 ⁄ 综合 ⁄ 共 5230字 ⁄ 字号 评论关闭
1.模板的友员函数
  1. template <typename T> 
  2. class Creator { 
  3.     friend void feed(Creator<T>*){  // every T generates a different 
  4.                                     // function ::feed() 
  5.         std::cout << "feed(Createor<" << typeid(T).name() << ">*)/n";
  6.     } 
  7. }; 

 

每个特例化Creator都会生成一个普通的feed函数,这样友员函数的使用也会引用模板的instantiate(实例化)

  1.     Creator<void> c1;
  2.     feed(&c1);
  3.     Creator<double> c2;
  4.     feed(&c2);

 

2.ADL

argument-dependent lookup (ADL)

特殊的名字搜索机制,注意如果名字有了修饰符则这一机制不会被启用

  1. template <typename T> 
  2. inline T const& max (T const& a, T const& b) 
  3.     return a < b ? b : a; 
  4. namespace BigMath { 
  5.     class BigNumber { 
  6.     }; 
  7.     bool operator < (BigNumber const&, BigNumber const&); 
  8. using BigMath::BigNumber; 
  9. void g (BigNumber const& a, BigNumber const& b) 
  10.     BigNumber x = max(a,b); 

 

如果没有ADL,那么BigNumber x=max(a,b);将失败,因为max不知道BigMath这个名字空间

 

3.ADL更多名字线索

Otherwise, if the name is followed by a list of argument expressions enclosed in parentheses, ADL proceeds by looking up the name in namespaces and classes "associated with" the types of the call arguments.

  1. class _Clsordinary
  2. {
  3. public:
  4.     friend void notfound()
  5.     { std::cout << "not be found/n"; }
  6.     friend void ff(_Clsordinary& o)
  7.     {
  8.         std::cout << "with _Clsordinary, can be find/n";
  9.     }
  10. };

参数与被包括的搜索范围的关系

The precise definition of the set of associated namespaces and associated classes for a given type is determined by the following rules:

  • For built-in types, this is the empty set.

  • For pointer and array types, the set of associated namespaces and classes is that of the underlying type.

  • For enumeration types, the associated namespace is the namespace in which the enumeration is declared. For class members, the enclosing class is the associated class.

  • For class types (including union types) the set of associated classes is the type itself, the enclosing class, and any direct and indirect base classes. The set of associated namespaces is the namespaces in which the associated classes are declared. If the class is a class template instantiation, then the types of the template type arguments and the classes and namespaces in which the template template arguments are declared are also included.

  • For function types, the sets of associated namespaces and classes comprise the namespaces and classes associated with all the parameter types and those associated with the return type.

  • For pointer-to-member-of-class-X types, the sets of associated namespaces and classes include those associated with X in addition to those associated with the type of the member. (If it is a pointer-to-member-function type, then the parameter and return types can contribute too.)

    1. #include <iostream> 
    2. namespace X { 
    3.     template<typename T> void f(T); 
    4. namespace N { 
    5.     using namespace X; 
    6.     enumE{e1}; 
    7.     void f(E) { 
    8.         std::cout << "N::f(N::E) called/n"
    9.     } 
    10. void f(int
    11.     std::cout << "::f(int) called/n"
    12. int main() 
    13.     ::f(N::e1);  // qualified function name: no ADL 
    14.     f(N::e1);    // ordinary lookup finds ::f() and ADL finds N::f(), 
    15. }                // the latter is preferred 

4.模板类内部的类名字

模板类中类名字可以在不带模板参数列表情况下做为类型名字使用,但它不会被认为是一个模板。我们可以在它前面加修改符::,让它不再是一个内部类型。

  1. template<template<typenameclass TT> class X { 
  2. }; 
  3. template<typename T> class C { 
  4.    Ca;        // OK: same as ''C<T> a;'' 
  5.    C<void> b; // OK 
  6.    X<C> c;    // ERROR: C without a template argument list 
  7.               //        does not denote a template 
  8.    X<::C> d;  // ERROR: <: is an alternative token for [ 
  9.    X< ::C> e; // OK: the space between < and :: is required 

这里有个题外问题就是<:会被做成一个替换token看待,需要在它们之间加入空白符加以区分。

 

5.模板名字的组成

  1. template<typename1 T> 
  2. struct S: typename2 X<T>::Base { 
  3.     S(): typename3 X<T>::Base(typename4 X<T>::Base(0)) {} 
  4.     typename5 X<T> f() { 
  5.         typename6 X<T>::C * p;  // declaration of pointer p 
  6.         X<T>::D * q;            // multiplication! 
  7.     } 
  8.     typename7 X<int>::C * s; 
  9. }; 
  10. struct U { 
  11.     typename8 X<int>::C * pc; 
  12. }; 

6.ADL的蛋与鸡的问题

  1. namespace N { 
  2.     class X { 
  3.     }; 
  4.     template<int I> void select(X*); 
  5. void g (N::X* xp) 
  6.     select<3>(xp);  // ERROR: no ADL! 
  7. }

这也是模板名字的组成所造成的,名字由需要多个成分来确定。

要让ADL起作用,前提是xp必须被解释成一个函数的参数,而要使用select<3>()被解释为一个函数调用,必须知道select是一个模板,而这必须是ADL起作用的情况下,根据xp的类型来确定的。

 

7.模板参数的地位

在存在非参数依赖的类型的情况下,类型声明优先选择父类的类型声明

  1. template<typename X> 
  2. class Base { 
  3.   public
  4.     int basefield; 
  5.     typedef int T; 
  6. }; 
  7. class D1: public Base<Base<void> > {  // not a template case really 
  8.   public
  9.     void f() { basefield = 3; }       // usual access to inherited member 
  10. }; 
  11. template<typename T> 
  12. class D2 : public Base<double> {      // nondependent base 
  13.   public
  14.     void f() { basefield = 7; }       // usual access to inherited member 
  15.     T strange;        // T is Base<double>::T, not the template parameter! 
  16. }; 

8.参数依赖问题的解决办法

  1. template<typename T> 
  2. class DD : public Base<T> {      // dependent base 
  3.   public
  4.     void f() { basefield = 0; }  // (1) problem… 
  5. }; 
  6. template<>  // explicit specialization 
  7. class Base<bool> { 
  8.   public
  9.     enum { basefield = 42 };    // (2) tricky! 
  10. }; 
  11. void g (DD<bool>& d) 
  12.     d.f();                      // (3) oops? 

使用延迟搜索或者添加修饰符::,或者使用引入using

  1. // Variation 1: 
  2. template<typename T> 
  3. class DD1 : public Base<T> { 
  4.   public
  5.     void f() { this->basefield = 0; }  // lookup delayed 
  6. }; 
  7. // Variation 2: 
  8. template<typename T> 
  9. class DD2 : public Base<T> { 
  10.   public
  11.     void f() { Base<T>::basefield = 0; } 
  12. };
  13. // Variation 3: 
  14. template<typename T> 
  15. class DD3 : public Base<T> { 
  16.   public
  17.     using Base<T>::basefield;    // (1) dependent name now in scope 
  18.     void f() { basefield = 0; }  // (2) fine 
  19. }; 

抱歉!评论已关闭.