从 类 继承作为模板参数传递给构造函数并从它们继承
Inherit from classes passed to constructor as a template parameters an inherit from them
我想要这样的东西:
template<class... Args>
class MyClass : public Args
{
MyClass<class... Args>(/*some parameters*/)
{ }
}
// ana then:
MyClass<Base1, Base2, Base3>(/*some arguments*/)
我想 dynamic_cast
到 Base1
等等,并使用他的方法。
我知道这段代码行不通,但你有什么想法吗?
这很好用:
struct Base1
{};
struct Base2
{};
struct Base3
{};
template<class... Args>
struct MyClass : public Args...
{};
MyClass<Base1, Base2, Base3> mc;
构造函数中不需要 <>
,public Args
后缺少“...”并且缺少“;”在 class 定义的末尾。
让我按照您的要求向您展示一些工作示例:
#include<iostream>
class B1 {
private:
int *m;
public:
B1() { m = new int;}
~B1() { delete m;}
void SetM(int a) { *m = a;}
int GetM() { return *m;}
};
class B2 {
private:
std::string str;
public:
B2() { str = "";}
~B2() {}
void SetStr(std::string a) { str = a;}
std::string GetStr() { return str;}
};
class B3 {
private:
float f;
public:
B3() { f = 0.0 ;}
~B3() {}
void SetF(float a) { f = a;}
float GetF() { return f;}
};
template<class... Args>
class MyClass : public Args... {
};
int main () {
MyClass<B1,B2,B3> l;
l.SetM(1);
if (auto a = dynamic_cast<B1*>(&l)) {
std::cout<<" " << a->GetM() <<"\n";
} else {
std::cout<<"ERROR:\n";
}
}
希望这对您有所帮助,
谢谢,
拉库玛
I know that this code will not work, but do you have any ideas how to do it?
要让它发挥作用,您必须
(1)添加省略号(...
)继承Args...
class MyClass : public Args...
// ........................^^^
(2) 使 MyClass
成为 struct
或使 public
成为构造函数
(3) 删除定义构造函数的 <class... Args>
部分(它是隐式的)
(4) 增加一些如下
Args const & ... as
对于构造函数参数
(5) 添加分号结束 class 或 struct
现在下面的代码可以工作了
struct Base1 {};
struct Base2 {};
struct Base3 {};
template<class... Args>
struct MyClass : public Args...
{
MyClass (Args const & ...)
{ }
};
int main()
{
MyClass<Base1, Base2, Base3>(Base1{}, Base2{}, Base3{});
MyClass(Base1{}, Base2{}, Base3{}); // C++17 only
}
观察 main()
中的最后一行
MyClass(Base1{}, Base2{}, Base3{}); // C++17 only
仅适用于 C++17,因为使用了新的 C++17:演绎指南。
在您的情况下,有一个隐式推导指南允许从传递给构造函数的参数类型推导 class 的模板类型。
另一个使用示例(更有用?)可以是
MyClass mc{ Base1{}, Base2{}, Base3{} };
一开始,您使用的语法无效。使用可变参数模板时,需要'unpack'它们(正确的术语:'expand the parameter pack')使用它们时:
template<typename... Args>
class MyClass : public Args ...
// ^^^
{ };
在构造函数中,您可以完全跳过模板参数,但是如果您指定它们,您需要再次'unpack'它们:
MyClass<Args ...>(/*some parameters*/);
// ^^^^^^^^^^ optional
定义 class 后,您可以像使用 classic 模板一样指定模板参数,唯一不同的是数字:
MyClass<Base1> c1;
MyClass<Base1, Base2> c2;
MyClass<Base1, Base2, Base3> c3;
从 C++17 开始,使用适当的构造函数,您甚至可以推导 class 模板参数:
template<typename... Args>
class MyClass : public Args ...
{
public:
MyClass(Args const&... args)
: Args(args)... // call base class copy constructors!
// (note the unpacking again)
{ }
MyClass(Args&&... args)
: Args(std::forward(args))... // call base class move constructors!
// (note the unpacking again)
{ }
};
MyClass c0;
MyClass c1(Base1());
MyClass C2(Base1(), Base2());
std::cout << std::is_same_v<decltype(c0), MyClass<>> << std::endl;
std::cout << std::is_same_v<decltype(c1), MyClass<Base1>> << std::endl;
std::cout << std::is_same_v<decltype(c2), MyClass<Base1, Base2>> << std::endl;
请注意,继承在这里是一个转移注意力的问题,没有继承也可以。参见 class template argument deduction。
我想要这样的东西:
template<class... Args>
class MyClass : public Args
{
MyClass<class... Args>(/*some parameters*/)
{ }
}
// ana then:
MyClass<Base1, Base2, Base3>(/*some arguments*/)
我想 dynamic_cast
到 Base1
等等,并使用他的方法。
我知道这段代码行不通,但你有什么想法吗?
这很好用:
struct Base1
{};
struct Base2
{};
struct Base3
{};
template<class... Args>
struct MyClass : public Args...
{};
MyClass<Base1, Base2, Base3> mc;
构造函数中不需要 <>
,public Args
后缺少“...”并且缺少“;”在 class 定义的末尾。
让我按照您的要求向您展示一些工作示例:
#include<iostream>
class B1 {
private:
int *m;
public:
B1() { m = new int;}
~B1() { delete m;}
void SetM(int a) { *m = a;}
int GetM() { return *m;}
};
class B2 {
private:
std::string str;
public:
B2() { str = "";}
~B2() {}
void SetStr(std::string a) { str = a;}
std::string GetStr() { return str;}
};
class B3 {
private:
float f;
public:
B3() { f = 0.0 ;}
~B3() {}
void SetF(float a) { f = a;}
float GetF() { return f;}
};
template<class... Args>
class MyClass : public Args... {
};
int main () {
MyClass<B1,B2,B3> l;
l.SetM(1);
if (auto a = dynamic_cast<B1*>(&l)) {
std::cout<<" " << a->GetM() <<"\n";
} else {
std::cout<<"ERROR:\n";
}
}
希望这对您有所帮助, 谢谢,
拉库玛
I know that this code will not work, but do you have any ideas how to do it?
要让它发挥作用,您必须
(1)添加省略号(...
)继承Args...
class MyClass : public Args...
// ........................^^^
(2) 使 MyClass
成为 struct
或使 public
成为构造函数
(3) 删除定义构造函数的 <class... Args>
部分(它是隐式的)
(4) 增加一些如下
Args const & ... as
对于构造函数参数
(5) 添加分号结束 class 或 struct
现在下面的代码可以工作了
struct Base1 {};
struct Base2 {};
struct Base3 {};
template<class... Args>
struct MyClass : public Args...
{
MyClass (Args const & ...)
{ }
};
int main()
{
MyClass<Base1, Base2, Base3>(Base1{}, Base2{}, Base3{});
MyClass(Base1{}, Base2{}, Base3{}); // C++17 only
}
观察 main()
MyClass(Base1{}, Base2{}, Base3{}); // C++17 only
仅适用于 C++17,因为使用了新的 C++17:演绎指南。
在您的情况下,有一个隐式推导指南允许从传递给构造函数的参数类型推导 class 的模板类型。
另一个使用示例(更有用?)可以是
MyClass mc{ Base1{}, Base2{}, Base3{} };
一开始,您使用的语法无效。使用可变参数模板时,需要'unpack'它们(正确的术语:'expand the parameter pack')使用它们时:
template<typename... Args>
class MyClass : public Args ...
// ^^^
{ };
在构造函数中,您可以完全跳过模板参数,但是如果您指定它们,您需要再次'unpack'它们:
MyClass<Args ...>(/*some parameters*/);
// ^^^^^^^^^^ optional
定义 class 后,您可以像使用 classic 模板一样指定模板参数,唯一不同的是数字:
MyClass<Base1> c1;
MyClass<Base1, Base2> c2;
MyClass<Base1, Base2, Base3> c3;
从 C++17 开始,使用适当的构造函数,您甚至可以推导 class 模板参数:
template<typename... Args>
class MyClass : public Args ...
{
public:
MyClass(Args const&... args)
: Args(args)... // call base class copy constructors!
// (note the unpacking again)
{ }
MyClass(Args&&... args)
: Args(std::forward(args))... // call base class move constructors!
// (note the unpacking again)
{ }
};
MyClass c0;
MyClass c1(Base1());
MyClass C2(Base1(), Base2());
std::cout << std::is_same_v<decltype(c0), MyClass<>> << std::endl;
std::cout << std::is_same_v<decltype(c1), MyClass<Base1>> << std::endl;
std::cout << std::is_same_v<decltype(c2), MyClass<Base1, Base2>> << std::endl;
请注意,继承在这里是一个转移注意力的问题,没有继承也可以。参见 class template argument deduction。