C++ 17/20/23可变参数模板类继承使用示例(低于c++17可参考)

#include 

// 测试类
class BaseA
{
public:
	void print(int v){ std::cout << __FUNCTION__ << " value : " << v << std::endl; }
};

class BaseB
{
public:
	void print(const std::string_view str){ std::cout << __FUNCTION__ << " value : " << str << std::endl; }
};


class BaseC
{
public:
	BaseC(int a = 1, double d = 1.1, std::string str = "")
	{
		std::cout << "a: " << a << " d: " << d << " str: " << str << std::endl;
	}
	~BaseC() {}
public:
	void print(double d) { std::cout << __FUNCTION__ << " value : " << d << std::endl; }
};

/************************************************VariableTypeClass_A 可变数量类继承模板***********************************************************/

// 未提供构造函数 通过模板实例化或{}进行构造对象
template
class VariableTypeClass_A: public Args...
{
public:
	// 如果继承了Args类,并且类中的函数print是重载关系。
		// 需要通过using进行声明. 如果继承的基类中函数相同,并且都用了using声明,则会报歧义错。
	using Args::print...;
};

// 未提供构造函数 类外提供推倒方式 进行声明,达到根据参数个数,确定类型个数并实例化类。
template
class VariableTypeClass_B : public Args...
{
public:
	// 如果继承了Args类,并且类中的函数print是重载关系。
		// 需要通过using进行声明. 如果继承的基类中函数相同,并且都用了using声明,则会报歧义错。
	using Args::print...;
};

template
VariableTypeClass_B(Args...)->VariableTypeClass_B;


// 提供构造函数
template
class VariableTypeClass_C : public Args...
{
public:
	// 通过 {}... 或 ()... 推断类型实例化基类
	VariableTypeClass_C(const Args&... args) : Args{ args }... {}
	//VariableTypeClass_C(const Args&... args) : Args(args)...{}

public:
	// 如果继承了Args类,并且类中的函数print是重载关系。
		// 需要通过using进行声明. 如果继承的基类中函数相同,并且都用了using声明,则会报歧义错。
	using Args::print...;
};

// 为继承的每个类,提供不同参数的构造函数(可变参数构造函数). 需要类外提供推倒方式 进行声明
template
class VariableTypeClass_D : public Args...
{
public:
	template
	VariableTypeClass_D(Ts&&... args) : Args( std::forward(args))...{}

public:
	// 如果继承了Args类,并且类中的函数print是重载关系。
		// 需要通过using进行声明. 如果继承的基类中函数相同,并且都用了using声明,则会报歧义错。
	using Args::print...;
};

template 
VariableTypeClass_D(Args&&...)->VariableTypeClass_D...>;


/// test function
void test_VariableTypeClass_A();
void test_VariableTypeClass_B();
void test_VariableTypeClass_C();
void test_VariableTypeClass_D();

/*************
 * 总结: 如果在实例化类对象时,不通过<>显示对象实例化。通过参数隐式类型推导要继承的类型。
 *		① 必须在类中提供非模板 构造函数如 test_VariableTypeClass_C
 *		② 在实例化对象时通过{}方式进行实例化如 test_VariableTypeClass_A
 *		③ 在类外 提供可变参数声明 template VariableTypeClass_B(Args...)->VariableTypeClass_B; 如 test_VariableTypeClass_B
 *		注意: 如果构造函数为模板构造函数,同样需要提供 可变参推倒声明。如 test_VariableTypeClass_D
 *			  仅适用通过参数推导类型。因为提供了拷贝构造方式构造基类,所以要有对象。
 ************/

/// 附 继承一种类型,但该类型的参数可变

// 继承类可变参构造(针对不同类的构造函数不同)
template
class VariableConstructor_A : public T
{
public:
	template
	VariableConstructor_A(Args... args):T(args...) {}
};

template
class VariableConstructor_B : public T
{
public:
	template
	VariableConstructor_B(Args&&... args) :T(std::forward(args)...) {}

public:
	using T::print;
};

void test_VariableConstructor()
{
	VariableConstructor_B c(1,1.1,"ssss");

	c.print(1.1);
}



int main()
{
	//test_VariableTypeClass_A();
	//test_VariableTypeClass_B();
	//test_VariableTypeClass_C();
	//test_VariableTypeClass_D();
	test_VariableConstructor();

	return 0;
}

void test_VariableTypeClass_D()
{
	BaseA a;
	BaseB b;
	VariableTypeClass_D vatd_1(a,b);
	vatd_1.print("VariableTypeClass_D");


}

void test_VariableTypeClass_C()
{
	BaseA a;
	BaseB b;
	VariableTypeClass_C vatc_1(a,b);
	vatc_1.print("VariableTypeClass_C");
}

void test_VariableTypeClass_B()
{
	BaseA a;
	BaseB b;
	VariableTypeClass_B vtb_1(a,b);
	vtb_1.print("类外提供推到方式..");
}

void test_VariableTypeClass_A()
{
	// 使用方式 1 通过模板<>实例化
	VariableTypeClass_A	vta_1;
	vta_1.print("hello world.");

	// 使用方式 2 如果VariableTypeClass_A类中没有提供构造函数,通过 {基类对象A,基类对象B...} 方式进行类型推断构造
	BaseA a;
	BaseB b;
	VariableTypeClass_A vta_2{ a,b };
	vta_2.print("2");
}

你可能感兴趣的:(C/C++,c++)