【C++】 typedef typename

typedef

  typedef 官方的解释如下:

typedef - creates an alias that can be used anywhere in place of a (possibly complex) type name.

  也就是说用来给类型名创建一个别名(alias),同时,typedef 可以出现在类型名的任何位置

简单的别名创建

  最简单的例子如下:

typedef unsigned long long ull; // unsigned typedef long long ull; 也可以
unsigned long long a = 1;
ull b = 1;
ull(c) = 1;	// 和 ull b = 1; 一样

不仅 typedef 可以出现在类型名中的任何位置,类型名的顺序也可以是乱的:

// typedef can be used anywhere in the decl-specifier-seq
long unsigned typedef int long ullong;
// more conventionally spelled "typedef unsigned long long int ullong;"

  a、b 的类型是一样,ull 明显比 unsigned long long 要简单很多。

数组名的别名创建

  typedef 还可以用于数组名的别名创建,如下所示:

typedef int arr_t[10];
// the following two objects have the same type
int a1[10];
arr_t a2;

  数组大小不能是变量,但可以是常量,比如 const int n = 10; 或者 constexpr int n = 10; 。

多个别名的创建

  typedef 还可以用于多个别名的创建,用 逗号 分隔,如下所示:

typedef int int_t, *intp_t, arr_t[10];
int_t a;	// int a;
intp_t b;	// int* b;
arr_t c;	// int c[10];

函数的别名创建

  typedef 还可以用于函数别名的创建,如下:

int func(int a, int b) {
	return a + b;
}
	
int main()
{
	typedef int fp1(int, int), (&fp2)(int, int), (*fp3)(int, int);
	
	fp1* f1 = func;	// 函数名就是函数指针
	fp2  f2 = func;
	fp3  f3 = func;
	
	auto res = func(1, 2);
	auto res0 = (&func)(1, 2);
		
	auto res1 = f1(1, 2);
	auto res2 = f2(1, 2);
	auto res3 = f3(1, 2);
	printf("%d %d %d %d %d\n", res, res0, res1, res2, res3);	// 3 3 3 3 3
	reutrn 0;
}

  上边几个函数定义看的眼花缭乱,但是意思大概就是,typedef int (函数); 定义了一个返回值是 int 类型的函数类型。因为函数名就是函数指针,所以如果是 typedef int fp1(int, int); 那就需要 fp1* f1 = func; 。参数列表需要一致。这样比较长的函数名就可以用简化的名字来调用了。值得注意的是,函数的调用,除了 func(1, 2); 竟然还可以 (&func)(1, 2); 但是不能 &func(1, 2); 。大神说,在windows 平台下用 min、max 函数,最好的方式是 (&std::max)(1, 2); 这样就不会被当做 <windows.h> 中宏定义的 max 函数,当然也可以 #define NOMINMAX 但是如果没有加,就会混淆。
  下边的例子是用在类中的函数别名使用。

typedef void print_int(int);
typedef bool is_equal(const std::string& s1, const std::string& s2, size_t size, size_t& idx);
class X {
	public:
		static print_int(x_int);   // static void x_int(int);
		static is_equal(x_string); // static bool x_string(const std::string& s1, const std::string& s2, size_t size, size_t& idx);
};
	
void X::x_int(int a){
	cout << a << endl;
}
	
bool X::x_string(const std::string& s1, const std::string& s2, size_t size, size_t& idx){
	return false;
}

  所以,比如看到一句: typedef Pointer (*CopyFunction)(const Pointer); 那可以用 CopyFunction 作为类型名,对函数进行创建。

用于模板

  typedef 还可以用于模板,如下:

template< class T>
struct add_const {
	typedef const T type;
};

  typedef 可以和任何限定名一起使用,除了类型限定名。

The typedef specifier cannot be combined with any other specifier except for type-specifiers.

  也就是说,下边这种写法是不行的:

typedef static unsigned int uint;

  VS 会提示 “不能指定多个存储类”。

typename

  typename 有三种用法:
  1、告诉编译器,后边这个东西是个类型
  2、在 typedef 中使用,用于告诉编译器,后边这个东西是个类型;
  3、用于 template < typename T >,和 template < class T > 一模一样的作用。

// 1
template <class T>
void foo() {
	typename T::iterator * iter;
	// ...
}

// 2
typedef typename __type_traits<T>::has_trivial_destructor trivial_destructor;

// 3
template <typename T>
int compare(const T &v1, const T &v2) {
	if (v1 < v2) return -1;
	if (v2 < v1) return 1;
	return 0;
}

  第三种用法没什么好说的,主要看前两种用法。上边已经说了很多 typedef 的用法,没有看到 typename 出现,那么它是干嘛的呢。在 C++ 标准中写道:

A name used in a template declaration or definition and that is dependent on a template-parameter is assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified by the keyword typename.

  就是说,对于用于模板定义的依赖于模板参数的名称,只有在实例化的参数中存在这个类型名,或者这个名称前使用了typename关键字来修饰,编译器才会将该名称当成是类型。除了以上这两种情况,绝不会被当成是类型。(https://blog.csdn.net/vanturman/article/details/80269081)
  对于 T::iterator,T 类型下边的 iterator 不一定是个类型,有可能是个变量,如下:

template <class T>
void foo() {
	T::iterator * ite;
	// ...
}
	
struct A {
	static int iterator
	// ...
};

  这样的话这个变量声明就变得很奇怪,变成了一个乘法。所以在VS中,T::iterator * ite; 这行会提示 "Dependent type requires using ‘typename’ keyword"。也就是需要改成 typename T::iterator * iter; 用于显式告诉编译器,T::iterator 是一个类型。
  第二种用法也是这种意思,如果类型是依赖于模板参数的限定名,那么在它之前必须加 typename。其它情况下 typename 是可选的,也就是说对于一个不是依赖名的限定名,该名称是可选的,例如 vector vi;
  不过在基类列表中,typename 可以不写:
在这里插入图片描述

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值