C++模板元编程(三)

C++模板元编程(三)

typename和template关键字

  正确的使用关键字typename与template可以很多细微的语法错误,总结如下。

  1. template关键字用来引入模板声明和定义,如:

template <class T> class Vector;

  2. typename关键字通常用来取代class来声明模板类型的参数,如:

template <typename T> class Vector;

  3. typename关键字和class关键字在声明模板类型参数时,一般情况下等价(区别见后面)。但有时选用其中某个关键字,在概念上更加明确,如:

// 模板参数中,第一个是声明一个type参数,第二个是一个类型为T::value_type的值。
// 可见第二种方式,概念更明确,虽然两种模板声明都可以。 
template<typneame T, typename T::value_type> class Test;
template<class T, typename T::value_type> class Test;

  4. 当一个依赖名表示的是一个依赖性的类型时,需要使用typename关键字(对非依赖名,是否使用typename关键字对其进行限定完全是可选的),如:

template<typename Tp>
class IteratorTraits
{
    public:
        // 当使用一个依赖性的类型,且该名字表示一个类型时,C++标准要求使用typename关键字表明该依赖名是一个类型
        typedef typename Tp::value_type value_type;
        typedef typename Tp::reference reference;
        typedef typename Tp::pointer pointer;
        typedef typename Tp::difference_type difference_type;
        typedef typename Tp::iterator_category iterator_category;
};

template<typename T>
class Test
{
    public:
        typename std::vector<T> v; // typename是可选的
    // typedef typename int value_type; //(错误) typename不能用在非限定性(也就是不带::前缀)上
};

// typedef typename int value; // (错误)typename不能使用在模板之外的任何场合

// typename不能用于基类的名字上,即便它是依赖性的也不行
template<class T> struct Base;

template<class T> struct Derived 
    : typename Base<T>::type // (错误)
{};

// typename不能用于友元声明中
template<class T> class Test
{
    friend class typename T::type;
};

  5. 当一个依赖名是成员模板时,需要使用template消除歧义,如:

template<class T>
int f(T& x)
{
    // x.convert成员函数模板,需要使用template关键字。不然的话可能会将convert当做数据成员,
    // 而解析为(x.convert < 3) > pi, 从而造成歧义
    return x.template convert<3>(Pi)
}

// 注:template禁止用在模板之外的任何场合,包括显示(完全)模板特化。也不能出现在using声明中

参考资料

  1. 《C++模板元编程》(David Abrahams, Aleksey Gurtovoy )

你可能感兴趣的:(C++,template)