c++ typename用法

先看这两篇文章。 

https://blog.csdn.net/vanturman/article/details/80269081

https://blog.csdn.net/pizzq/article/details/1487004

使用typename的规则

最后这个规则看起来有些复杂,可以参考MSDN

  • typename在下面情况下禁止使用:
    • 模板定义之外,即typename只能用于模板的定义中
    • 非限定类型,比如前面介绍过的intvector<int>之类
    • 基类列表中,比如template <class T> class C1 : T::InnerType不能在T::InnerType前面加typename
    • 构造函数的初始化列表中
  • 如果类型是依赖于模板参数的限定名,那么在它之前必须加typename(除非是基类列表,或者在类的初始化成员列表中)
  • 其它情况下typename是可选的,也就是说对于一个不是依赖名的限定名,该名称是可选的,例如vector<int> vi;

一句话,如果是用于模板定义的依赖于模板参数名称(除非是基类列表,或者在类的初始化成员列表中),那么只有使用typename修饰编译器才会将改名称当成类型. 

上面注意两点:

1.记住这里修饰的是限定名,而不是限定名后面的变量!!

2.这里说的是类型依赖于模板参数,是模板参数不是类型,比如MyClass<T>,这是一个类型。

template <typename T>
class MyClass
{
public:
	typename T::myIterator a;
	typename T::myIterator2 b = 4;
private:
};

class ContatinsType
{
public:
	struct myIterator{ };
	typedef int myIterator2;
private:
};

看这句:typename T::myIterator a; 这里的myIterator是限定名(使用了限定符::),也依赖于模板名称(使用了T)

因此这里一定要使用typename 修饰表明这里的限定名myIterator(typename修饰的是限定名,而不是a,b)是一个类型名称。如果不用,看下面的代码,我们将代码修改如下:

template <typename T>
class MyClass
{
public:
	T::myIterator a;
private:
};

class ContatinsType
{
public:
	static int myIterator;
private:
};
int ContatinsType::myIterator = 5;

这里MyClass没有使用typename修饰myIterator,那怎么知道这是一个名称,还是变量,而且它在类ContainsType中的确是一个变量!!

以上可以看出,依赖于模板名称的限定名可以是变量(上面那个就是),可以是一个函数,也可以是一个类型(上上面的代码段),那么不使用typename修饰怎么知道这个限定名是类型名称!

下面举例说明不需要typename的例子。

#include <iostream>
#include <vector>

using namespace std;

template <typename T>
class ContatinsType
{
public:
	typedef int myInt;
private:
};
template <typename T>
class MyClass
{
public:
	typedef ContatinsType<int>::myInt myInt2;
private:
};

int main()
{
	MyClass<ContatinsType<int>>::myInt2 i2 = 3;
	cout << "i2:  "<< i2<< endl;
}

为什么这里只是使用了typedef ContainsType<int>::myInt myInt2;因为这里ContainsType<int>是一个类型,也就是说myInt不是依赖模板参数的限定符!!所以,这里的typename可以不使用。

通常我们会在模板里使用它,例子如下:

template<typename T>
class MyIteator
{
public:
	static T a;//只是声明,并没有定义
};
int MyIteator<int>::a = 3;//类内static成员类外定义

template <typename T>
class MyClass
{
public:
	using _MyBase = MyIteator<T>;
	using _iteator = typename _MyBase;//使用typename表明 _MyBase是一个类名称,而非什么变量,表达式等等
};

int main()
{
	MyClass<int>::_iteator myIteator;
	cout << myIteator.a << endl;
}

这样使用的方式和vector<int>::iteator i_iteator;这样声明一个vector<int>::iteator类型的对象很相似。

上面MyClass还可以修改为:

template <typename T>
class MyClass
{
public:
	typedef typename MyIteator<T> _iteator;
};

 这里的_iteator是依赖于模板参数的名称,但它不是限定名,因此可以省略typename

template<typename T>
class MyIteator
{
public:
	static T a;//只是声明,并没有定义
};
int MyIteator<int>::a = 3;//类内static成员类外定义

template <typename T>
class MyClass
{
public:
	typedef MyIteator<T>* _iteator;
};

int main()
{
	MyClass<int>::_iteator myIteator;
	cout << myIteator->a << endl;
}

 像上面这样也是可以的。最好还是写上比较好,别人一看就知道是什么。

在泛型编程里,我们还经常使用一种叫特性的东西,先看代码:

#include <iostream>
#include <vector>

using namespace std;

//主模板
template <typename T> class SigmaTraits{};

template<> 
class SigmaTraits<char> {
public:
	typedef char ReturnType;
};

template<>
class  SigmaTraits<int>
{
public:
	typedef int ReturnType;
private:
};

template <typename T>
typename SigmaTraits<T>::ReturnType Sigma( const T const* start, const T const* end ) {
	typedef  typename SigmaTraits<T>::ReturnType ReturnType;
	int s = ReturnType();//Value initialization https://en.cppreference.com/w/cpp/language/value_initialization
	while (start!= end)
	{
		s += *start++;
	}
	return s;
}

int main()
{

	char vchar[] = "a";
	cout << Sigma<char>(vchar, vchar + strlen(vchar)) << endl;

	int nums[] = {1,2,3};
	cout << Sigma<int>(nums, nums + sizeof(nums)/sizeof(nums[0])) << endl;
}

模板类SigmaTraits叫做特性模板,它含有其参数型别T的一个特性,也就是ReturnType。

在模板函数Sigm( const T const* start, const T const* end )中就使用了typename, typedef  typename SigmaTraits<T>::ReturnType ReturnType; 使用 typename 表明限定名 SigmaTraits<T>::ReturnType 是一个类型名称。虽然在这个例子中你可以不使用typename,因为 SigmaTraits<T>是类型,不是模板参数T,只有是依赖于模板参数Td的限定名才会强制使用typename表明限定名是一个类型名称(开头提到的注意2: 这里说的是类型依赖于模板参数,是模板参数不是类型,比如MyClass<T>,这是一个类型)。

参考:

https://blog.csdn.net/pizzq/article/details/1487004

https://blog.csdn.net/vanturman/article/details/80269081

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值