专业编程基础技术教程

网站首页 > 基础教程 正文

C++模板编程-扩展标准库方法( break tie )

ccvgpt 2024-08-03 12:32:37 基础教程 19 ℃

一、各个模块

1、类模板参数类型与构造函数参数类型不同

C++模板编程-扩展标准库方法( break tie )

当构造函数的参数类型与类模板参数不同时,我们可以使用自定义的推导来引导,从而使得类模板参数类型是可以推导的。

	template<typename T>  // class template parameter T
	class ClassUnconnected
	{
	public:
		ClassUnconnected(const char* msg) // constructor parameter msg
		{									// between class template parameter T
											// and constructor parameter msg
											// there is no connection of any kind

		}
	};

	// class template parameter (or argument) deduction guide
	template<typename T> 
	ClassUnconnected(const T* msg) // constructor
		->		
	ClassUnconnected<T>;  // class template .. we are deducing the class template parameter T

2、类模板参数类型与构造函数参数类型相同

构造函数的参数msg与T相关,类模板参数T与构造函数参数相关,C++编译器可以推导类模板参数。ClassTied<T>,T可以使用构造函数参数推导。

template<typename T>	// class template parameter T
	class ClassTied
	{
	private:
		T m_value;
	public:
		ClassTied(const T* msg)  // constructor parameter msg
		{						// the type of msg is tied to T,the class template parameter
								// with this tie between constructor parameter and class template parameter	T
								// C++ complier can deduce the class template parameter
								// ClassTied<T>,this T can be deduced using constructor parameter.

		}
	};

3、类模板参数类型与构造函数参数类型相同,打断其相关性,并使得其可以运行

没有打断类模板参数T和其构造函数参数类型的相关性,我们自定义的推导引导无法工作。

幸运的是,在大多数C++标准库类中,打断相关性,我们可以得到自定义的推导规则的优势,这种优势可以让我们根据我们的需求来扩展标准库。

// we can extract the type of T
	// using tft::element_type_t<ClassBreakTheTie<T>>
	template<typename T>	// class template parameter T
	class ClassBreakTheTie	// ClassBreakTheTie<char>
	{
	private:
		T m_value;
	public:
		// the custom deduction guide
		// modifies the type of m_value on-the-fly
		// this was impossible before C++17
		template<typename S>
		ClassBreakTheTie(const S* msg) : m_value{ msg }
		{
		   // ClassBreakTheTie<char>::ClassBreakTheTie(const char* msg)
		}
	};

	// we defined class template parameter deduction guide for ClassBreakTheTie<S>
	template<typename S>  // S -> char
	ClassBreakTheTie(const S* msg)->// ClassBreakTheTie<char>::ClassBreakTheTie(const char* msg)
		ClassBreakTheTie<std::basic_string<S>>;	// ClassBreakTheTie<std::basic_string<char>>

二、整体代码

#include "pch.h"

auto stream = tpf::stream();
auto nl = stream.get_console_out();

namespace tft
{
	/*
	as we will soon see,the custom deduction guide works only when the constructor's
	parameter type is
	(1) Not tied to (or connected with) that of class template parameter.
	(2) the class template parameter type is deducible using the custom deduction guide.

	*/
	template<typename T>  // class template parameter T
	class ClassUnconnected
	{
	public:
		ClassUnconnected(const char* msg) // constructor parameter msg
		{									// between class template parameter T
											// and constructor parameter msg
											// there is no connection of any kind

		}
	};

	// class template parameter (or argument) deduction guide
	template<typename T> 
	ClassUnconnected(const T* msg) // constructor
		->		
	ClassUnconnected<T>;  // class template .. we are deducing the class template parameter T

	template<typename T>	// class template parameter T
	class ClassTied
	{
	private:
		T m_value;
	public:
		ClassTied(const T* msg)  // constructor parameter msg
		{						// the type of msg is tied to T,the class template parameter
								// with this tie between constructor parameter and class template parameter	T
								// C++ complier can deduce the class template parameter
								// ClassTied<T>,this T can be deduced using constructor parameter.

		}
	};

	/*
		without breaking the tie (or the vicious cycle) between the class template
		parameter T and its constructor parameter type,our custom deduction guide does not work

		Luckily,in the most of C++ standard library classes ,the vicious cycle (or tie)
		is broken such that we can take advantage of the custom deduction guide,
		which enables us to further extend C++ standard library to meet our needs
	
	*/

	// we can extract the type of T
	// using tft::element_type_t<ClassBreakTheTie<T>>
	template<typename T>	// class template parameter T
	class ClassBreakTheTie	// ClassBreakTheTie<char>
	{
	private:
		T m_value;
	public:
		// the custom deduction guide
		// modifies the type of m_value on-the-fly
		// this was impossible before C++17
		template<typename S>
		ClassBreakTheTie(const S* msg) : m_value{ msg }
		{
		   // ClassBreakTheTie<char>::ClassBreakTheTie(const char* msg)
		}
	};

	// we defined class template parameter deduction guide for ClassBreakTheTie<S>
	template<typename S>  // S -> char
	ClassBreakTheTie(const S* msg)->// ClassBreakTheTie<char>::ClassBreakTheTie(const char* msg)
		ClassBreakTheTie<std::basic_string<S>>;	// ClassBreakTheTie<std::basic_string<char>>

	// we have to break the tie between the constructor ClassBreakTheTie(const T* msg)
	// and the class ClassBreakTheTie<T>

}  // end of namespace tft

void deduction_guide_basic()
{
	tft::ClassTied t("this is literal string");
	using t_type = decltype(t);
	stream << "t's type: " << Tpf_GetTypeName(t_type) << nl;
	
	tft::ClassUnconnected u("this is a literal string");
	using u_type = decltype(u);
	stream << "t's type: " << Tpf_GetTypeName(u_type) << nl;
}

void deduction_guide_break_tie()
{
	// char

	tft::ClassBreakTheTie b("this is literal string");
	using b_type = decltype(b);
	/*
		please understand that tft::element_type_t<> function is
		indispensible and one of most frequently used type functions
		for advanced C++ programming.

		please make yourself familiarized with it. We will be using it over 
		and over again.
	*/
	using  element_t = tft::element_type_t<b_type>;

	stream << "b's type: " << Tpf_GetTypeName(b_type) << nl;
	stream << "the element type T of b_type: " << Tpf_GetTypeName(element_t) << nl;
	
	/// <summary>
	/// ////  wchar_t ////////////////////////////////////////////
	/// </summary>
	tft::ClassBreakTheTie w(L"this is literal string");
	using w_type = decltype(w);
	using w_element_t = tft::element_type_t<w_type>;

	stream << "w's type: " << Tpf_GetTypeName(w_type) << nl;
	stream << "the w element type T of b_type: " << Tpf_GetTypeName(w_element_t) << nl;
}

int main()
{
	deduction_guide_break_tie();
	return 0;
}

Tags:

最近发表
标签列表