C++ Templates

【C++ Templates(12)】模板中的名称

2018-05-14  本文已影响37人  downdemo

名称查找

ADL(Argument-Dependent Lookup)

int x;
class B {
public:
    int i;
};
class D : public B {
};
void f(D* pd)
{
    pd->i = 3; // finds B::i
    D::x = 2; // ERROR: does not find ::x in the enclosing scope
}
extern int count; // (1)
int lookup_example(int count) // (2)
{
    if (count < 0) {
    int count = 1; // (3)
    lookup_example(count); // refers to (3)
}
    return count + ::count; // 分别引用(2)、(1)
}
template <typename T>
inline T const& max (T const& a, T const& b)
{
    return a < b ? b : a;
}

namespace BigMath {
    class BigNumber {
        ...
    };
    bool operator < (BigNumber const&, BigNumber const&);
    ...
}
using BigMath::BigNumber;
void g (BigNumber const& a, BigNumber const& b)
{
    ...
    BigNumber x = ::max(a,b);
    ...
}
#include <iostream>

namespace X {
    template<typename T> void f(T);
}

namespace N {
    using namespace X;
    enumE { e1 };
    void f(E) {
        std::cout << "N::f(N::E) called\n";
    }
}

void f(int)
{
    std::cout << "::f(int) called\n";
}

int main()
{
    ::f(N::e1); // qualified function name: no ADL
    f(N::e1); // ADL finds N::f(),
}

友元名称插入

template<typename T>
class C {
    ...
    friend void f();
    friend void f(C<T> const&);
    ...
};

void g (C<int>* p)
{
    f(); // Is f() visible here?
    f(*p); // Is f(C<int> const&) visible here?
}

插入式类名称

#include <iostream>

int C;

class C {
private:
    int i[2];
public:
    static int f() {
        return sizeof(C);
    }
};

int f()
{
    return sizeof(C);
}

int main()
{
    std::cout << "C::f() = " << C::f() << "," // 类C的大小
        << " ::f() = " <<::f() << '\n'; // int的大小
}
template<template<typename> class TT> class X {
};

template<typename T> class C {
    C a; // OK: same as ''C<T> a;''
    C<void> b; // OK
    X<C> c; // 错误:C后没有实参列表,不被看作模板
    X<::C> d; // 错误: <:是[的另一种标记
    X< ::C> e; // OK: the space between < and :: is required
};
template<template<typename> class TT> class X {
};

template<typename T> class C {
    C* a;       // OK: same as “C<T>* a;”
    C<void>& b; // OK
    X<C> c;     // OK: C without a template argument list denotes the template C
    X<::C> d;   // OK: ::C is not the injected class name and therefore always
               //     denotes the template
};
template<int I, typename... T> class V {
    V* a;         // OK: same as “V<I, T...>* a;”
    V<0, void> b; // OK
};
template<typename T> class Node {
    using Type = T;
    Node* next;           // Node refers to a current instantiation
    Node<Type>* previous; // Node<Type> refers to a current instantiation
    Node<T*>* parent;     // Node<T*> refers to an unknown specialization
};
template<typename T> class C {
    using Type = T;

    struct I {
        C* c;               // C refers to a current instantiation
        C<Type>* c2;        // C<Type> refers to a current instantiation
        I* i;               // I refers to a current instantiation
    };
    struct J {
        C* c;               // C refers to a current instantiation
        C<Type>* c2;        // C<Type> *refers to a current instantiation
        I* i;               // I refers to an unknown specialization,
                        // because I does not enclose
        JJ* j;              // J refers to a current instantiation
    };
};
template<> struct C<int>::I {
    // definition of the specialization
};

解析模板

非模板中的上下文相关性

x*
identifier, type, x
symbol, *
identifier, nontype, x
symbol, *
X<1>(0)
(X<1)>0
template<bool B>
class Invert {
public:
    static bool const result = !B;
};
void g()
{
    bool test = B<(1>0)>::result; // parentheses required!
}
List<List<int>> a;
class X {
...
};
List< ::X> many_X;
template<typename T> struct G {};
struct S;
G<::S> gs;               // valid since C++11, but an error before that

#define F(X) X ## :

int a[] = { 1, 2, 3 }, i = 1;
int n = a F(<::)i];       // valid in C++98/C++03, but not in C++11

依赖型类型名称

template<typename T>
class Trap {
public:
    enum{x}; // (1) x is not a type here
};

template<typename T>
class Victim {
public:
    int y;
    void poof() {
        Trap<T>::x*y; // (2) declaration or multiplication?
    }
};

template<>
class Trap<void> { // evil specialization!
public:
    typedef int x; // (3) x is a type here
};

void boom(Trap<void>& bomb)
{
    bomb.poof();
}
template<typename T>
struct S: typename X<T>::Base {
    S(): typename X<T>::Base(typename X<T>::Base(0)) {}
    typename X<T> f() {
        typename X<T>::C * p; // declaration of pointer p
        X<T>::D * q; // multiplication!
    }
    typename X<int>::C * s;
};

struct U {
    typename X<int>::C * pc;
};

依赖型模板名称

template<typename T>
class Shell {
public:
    template<int N>
    class In {
        public:
        template<int M>
        class Deep {
            public:
                virtual void f();
        };
    };
};

template<typename T, int N>
class Weird {
public:
    void case1(Shell<T>::template In<N>::template Deep<N>* p) {
        p->template Deep<N>::f(); // 禁止虚函数调用
    }
    void case2(Shell<T>::template In<T>::template Deep<T>& p) {
        p.template Deep<N>::f(); // 禁止虚函数调用
    }
};
p.template Deep<N>::f()

using声明中的依赖型名称

class BX {
public:
    void f(int);
    void f(char const*);
    void g();
};
class DX : private BX {
public:
    using BX::f;
};
template<typename T>
class BXT {
public:
    using Mystery = T;
    template<typename U>
    struct Magic;
};

template<typename T>
class DXTT : private BXT<T> {
public:
    using typename BXT<T>::Mystery;
    Mystery* p; // would be a syntax error if not for the typename
};
template<typename T>
class DXTM : private BXT<T> {
public:
    using BXT<T>::template Magic; // ERROR: not standard
    Magic<T>* plink; // ERROR: Magic is not a known template
};
template<typename T>
class DXTM : private BXT<T> {
public:
    template<typename U>
    using Magic = typename BXT<T>::template Magic<T>; // Alias template
    Magic<T>* plink;                                    // OK
};

ADL和显式模板实参

namespace N {
class X {
        ...
    };
    template<int I> void select(X*);
}

void g (N::X* xp)
{
    select<3>(xp); // ERROR: no ADL!
}

派生和类模板

非依赖型基类

template<typename X>
class Base {
public:
    int basefield;
    using T = int;
};

class D1: public Base<Base<void> > { // 实际上不是模板
public:
    void f() { basefield = 3; }
};

template<typename T>
class D2 : public Base<double> { // 非依赖型基类
public:
    void f() { basefield = 7; }
    T strange; // T是Base<double>::T,而非模板参数
};
void g (D2<int*>& d2, int* p)
{
    d2.strange = p; // 错误:类型不匹配
}

依赖型基类

template<typename T>
class DD : public Base<T> { // dependent base
public:
    void f() { basefield = 0; } // (1) problem...
};

template<> // explicit specialization
class Base<bool> {
public:
    enum { basefield = 42 }; // (2) tricky!
};

void g (DD<bool>& d)
{
    d.f(); // (3) oops?
}
// 方案1:
template<typename T>
class DD1 : public Base<T> {
public:
    void f() { this->basefield = 0; } // lookup delayed
};

// 方案2:利用受限名称引入依赖性
template<typename T>
class DD2 : public Base<T> {
public:
    void f() { Base<T>::basefield = 0; }
};
template<typename T>
class B {
public:
    enumE { e1=6, e2=28, e3=496 };
    virtual void zero(E e = e1);
    virtual void one(E&);
};

template<typename T>
class D : public B<T> {
public:
    void f() {
        typename D<T>::E e; // this->E会是一个无效的语法
        this->zero(); // D<T>::zero()会禁止虚函数调用
        one(e); // one是依赖型名称,因为实参e类型(D<T>::E)是依赖型
    }
};
// 方案3:
template<typename T>
class DD3 : public Base<T> {
public:
    using Base<T>::basefield; // dependent name now in scope
    void f() { basefield = 0; } // fine
};
上一篇 下一篇

猜你喜欢

热点阅读