template语法总结(2)

最近闲来无事,在github上找打了facebook开发的基础库源码,在代码阅读的过程中,看到了很多新颖的template的语法。边看变查,同时记录一下,以免遗忘。

1.  std::enable_if定义

通过跳转其定义的头文件,可以看到标准库中对该模板函数的定义如下。若_Test变量的取值为false则type未定义,否则type定义为_Ty。

	// TEMPLATE CLASS enable_if
template
	struct enable_if
	{	// type is undefined for assumed !_Test
	};

template
	struct enable_if
	{	// type is _Ty for _Test
	typedef _Ty type;
	};

所以针对如下测试测试代码结果为:

int main()
{
	// EnableCheck的类型为void,代码可以编过
	using EnableCheck = std::enable_if::type;
	// EnableCheck的类型未定义,代码可以编不过
	// using EnableCheck = std::enable_if::type;

	return 0;
}

2.  template中匿名参数的使用

在template参数定义时,有时使用匿名参数来完成对部分参数条件的校验,只有校验通过才能够正常编译过,否则编译不过,如:

#include 

template
struct NoneInt
{
	static const bool value = true;
};

template<>
struct NoneInt
{
	static const bool value = false;
};

template ::value>::type>
RetType Func()
{
	std::cout << "hello" << std::endl;
	return 0;
}

int main()
{
	//可编译过
	Func();
	//可编译不过
	//Func();

	return 0;
}

其中第二个 匿名模板参数就是对返回值的校验,只有返回值为int才能够编译通过。

 

3.  对模板定义特换方式的学习:

模板特化不只是对模板参数列表中的部分(或全部)参数类型指定,以下的方式同样是特化:

template 
Fuction;

template 
Fuction
{

}

4.  偏特化仅适用于模板类,不适用于模板函数。而且偏特化中明确指定类型,在构造函数的类型实参中仍需要指定,除非在全模板中有指定默认参数。如下

template 
struct IsEnumUnderlying : std::false_type
{
};

template 
struct IsEnumUnderlying::value>::type>
: std::integral_constant::type>::value>
{
};

void TestDefaultParam()
{
    enum EnumType {};
    struct NonEnum {};

    // 调用偏特化版本
    IsEnumUnderlying a1;
    // 调用全定义版本
    IsEnumUnderlying a2;     
}

查看std::enable_if的定义可知,其仅对模板常数取值为true有Type定义,在模板推导时若模板常数取值为false将导致匹配失败。这种方式可用于对前置模板实参的条件限定,即只有同时匹配类型且满足限定条件时才能够完全匹配该模板定义。另外,类模板的构造函数不进行模板形参的类型推导。

5. 模板变参列表的使用

如下函数定义,第一个参数为函数指针,第二个参数为变参列表。在FunctionInvoke中调用该函数,通过forward将参数转发给对应的函数。标准库中的make_shared和thread的构造函数,都是采用与FunctionInvoke类型的定义方式。

template 
void FunctionInvoke(F f, Args... args)
{
	f(std::forward(args)...);
}

void printHello(int a)
{
	cout << "Hello" << endl;
}

void TestInvoker()
{
	FunctionInvoke(&printHello, 10);
}

6. 常量定义

template 
struct IsInt
{
	constexpr static bool value = false;
};

template <>
struct IsInt
{
	constexpr static bool value = true;
};

// 简化模板的使用
template 
constexpr bool IsInt_v = IsInt::value;

void Test()
{
    //调用方式如下,输出为false
    cout << IsInt_v << endl;
}

7. 移动语义和完美转发

std::move生成的是右值,std::forward是将原来的类型,转发给下一个参数使用(赋值或接口调用)。

 

你可能感兴趣的:(template语法总结(2))