迩来读《C++ Template》,或有语法规则之类,或有心得体会,恐过之既忘,遂聊记与此,供以后自勉参考。
-
关键字 typename 与 class 的区别与不同
- typename 的引入:两者的可以相互替代
一开始,只是有class, 一方面可以定义自定义类型,另一方面作为 template 的参数类型声明符号。但是template的参数也不一定是一个类,为了解决这种混淆,标准化的时候便引入了关键字 typename, 所以在下面这种简单情况下,两个关键字是可以互换的,不过 typename 更具有视觉上的说明性:
template <class Type> void output( Type ); // OK
template <typename Type> void output( Type ); // Ok
- 只能用 typename, 不能用 class 替代的地方
当我们在引用一个模板内部作为类型的成员时,就只能用 typename 了。如
class Test
{
public:
typedef int NewType;
...
};
template <class Type> // 可以与 typename 相互替代
void f( Type& TObj )
{
typedef typename Type::NewType NewType; //这时须用typename 显示说明
NewType varNewType;
}
这里的 NewType 类型是定义在类 Test 内部的,我们称之为嵌套类型,在此时我们需要显示用 typename 来说明这是一个类型,而不是其他的什么东西。
下面这个例子更具有说明性了:
template <class Type>
void f( Type& Obj )
{
Type::T( x ); // 函数调用,还是变量声明
}
可能我们是在调用Type内部的T() 函数,x作为函数的参数;也有可能我们是在定义一个类型为 T 的对象 x ( 这种声明方式是合法的,尽管这种方式有些别扭) 。
- 只能用class, 不能用 typename 替代的地方
我们知道模板的参数可以是模板,(template template parameter),此时我们必须用 class 关键字来显示说明这是一个类,不能用 typename。
template<typename T, template< typename T> class S> ... // Ok
template<typename T, template< typename T> typename S> ... // Error
此处只谈 template 的一些特殊用法.
看下面小程序:
class Memory { // 某个Allocator
public:
template <class T> T* get_new();
}
template <class Allocator> void f( Allocator& m )
{
int *p1 = m.get_new<int>(); // 语法错,在小于( < )后出现int
int *p2 = m.template get_new<int> (); // 对了,需要显示限定
}
这种情况主要出现在使用 一个模板成员函数的时候。
- 模板的模板参数 ( template template parameters )
模板的模板参数只能用于 模板类,而不能用于 模板函数。
模板的模板参数只能是 类模板,不能是函数模板。( 所以必须用class 关键字, 而不用 typename )
template <typename T,
template <typename ELEM> class CONT = std::deque >
class Stack {
private:
CONT<T> elems;
}
Stack<int,std::vector<int> > vStack; // ok
stack<int,std::vector> vStack; // ok
-
非型别类型参数 ( NonType template parameter )
语法约束: 必须是整形常量( 包括 enum )或者是外部对象链接指针
-
数组向指针的转化 ( array-to-pointer, 又称 decay( 退化) )
发生在参数不是引用类型的时候.
#include <string>
// note: nonreference parameters
// note: 非引用型参数
template <typename T>
inline T max (T a, T b)
{
return a < b ? b : a;
}
int main()
{
std::string s;
::max("apple","peach"); // OK: same type
::max("apple","tomato"); // OK: decays to same type
::max("apple",s); // ERROR: different types
}
下面是更好的说明:
// basics/refnonref.cpp
#include <typeinfo>
#include <iostream>
template <typename T>
void ref (T const& x)
{
std::cout << "x in ref(T const&): "
<< typeid(x).name() << '\n';
}
template <typename T>
void nonref (T x)
{
std::cout << "x in nonref(T): "
<< typeid(x).name() << '\n';
}
int main()
{
ref("hello"); // char [6]
nonref("hello"); // const char *
}
C++ 98 标准中,重载函数集合不能用模板参数推断,所以此时必须来显示指定。
template 的实例化就是一个函数集合,所以也须显示指定:
template <typename T, int VAL>
T addValue (T const& x)
{
return x + VAL;
}
std::transform (source.begin(), source.end(),
dest.begin(),
addValue<int,5>); // Error: 不能推断
std::transform (source.begin(), source.end(),
dest.begin(),
(int(*)(int const&)) addValue<int,5>); // Ok:
2023年9月25日 16:16
Kerala 2nd Standard Malayalam, English, Tamil, and Kannada Medium Textbook Available in SCERT Kerala Official Website, Students can Download Latest Edition, SCERT Kerala Standard Books are Prepared by a Group of Subject Expert, These SCERT Kerala Textbooks 2024 are an Excellent Resource for Students, as they can learn and revise through Different Chapters Present in the syllabus for SCERT Kerala 2nd Class Textbook 2024 Subjects like Maths, Science, Social Science, Hindi, English and Malayalam.This is Kerala Textbook.