C++17 CTAD(类模板实参推导)与C++17推导指引

直到 C++17, 使用类模板时都必须显式指出所有的模板参数的类型(除非它们有默认值) 。
从 C++17 开始, 这一要求不在那么严格了。如果构造函数能够推断出所有模板参数的类型(对
那些没有默认值的模板参数) , 就不再需要显式的指明模板参数的类型。
和函数模板不同, 类模板可能无法部分的推断模板类型参数(比如在显式的指定了一部分类
模板参数的情况下)

#include
#include
#include
using namespace std;

//C++17推导指引  是在CTAD(类模板实参推导)语义下在类模板推导上的指引优化;极大的避免了在CTAD环境下 造成的模板被初始化器泛滥性的非期望推导


template<typename T>
class MyStack {
private:
	std::vector<T> elems; // elements
public:
	MyStack(T elem) // initialize stack with one element
		: elems({ elem }) {}
	
};
//MyStack(char *)->MyStack;//推导指引的源类型char const *必须与参数类型完全一样;否则即便是char*类型;MyStack v("hello");依然不会进行指引的推导
//推导指引
MyStack(char const *)->MyStack<std::string>;


MyStack(int,int)->MyStack<void*>;//推导指引大致分二步:首先根据初始化器确定是否能被某个推导指引推导;推导出来后再根据实例化实现看其是否提供构造函数支持初始化器初始化动作

//推导指引模板【推导指引模板与主模板的模板参数是无关的,独立的参考 std::array的推导指引模板】
/*   std::array的推导指引模板
template 
array(T, U...) -> array;
*/
template <class _Iter,	enable_if_t<conjunction_v<_Is_iterator<_Iter>>, int> = 0>
MyStack(_Iter) -> MyStack<void*>;

//这个指引语句必须出现在和模板类的定义相同的作用域或者命名空间内。 通常它紧跟着模板
//类的定义。->后面的类型被称为推断指引的”guided type”。

class weight
{
public:
	weight(const string& str) {}
};


int main()
{
//!	weight str = "123";error:复制初始化隐式转换要求直接转换到目标类型,详见CPP

	MyStack v("hello");
	MyStack s{ "hello" };

	MyStack ss{3};
//!	MyStack ss{ 3 ,5};//指引推导成功,但是成功的实例化类型不支持{3,5}的初始化器初始化


//!	MyStack sr="hello";//推导指引成功,但是复制初始化失败【也是一种特殊的初始化器初始化失败,至于复制初始化为什么失败详见cpp】
	return 0;
}

你可能感兴趣的:(c++,开发语言,C++17,CTAD)