在c++中可以有一个包含类模板的向量吗

Can one have a vector containing class templates in c++?

本文关键字:向量 包含类 有一个 c++      更新时间:2023-10-16

我想创建一个结构/类,该结构/类至少有一个具有泛型类型的成员变量。T可以是从位集到字符数组的任何值。让我们称之为"场"。

然后,我想要一个包含Field对象的多个实例的列表/向量/数组。

这样的数据结构在C++中可能吗?

这就是我的解决方案现在的样子,因为而没有编译

错误C3203:"字段":未专用的类模板不能用作模板参数"_Ty"的模板参数,应为实际类型
错误C2955:"字段":使用类模板需要模板参数列表

class Main
{
public:
    template<typename T> class Field {
        public:
            CString name;
            bool state;
            T actualValue;
    };
    vector<Field> m_Message;
};

Field field1 = new Field();
field1.actualValue = 1;
Field field2 = new Field();
field2.actualValue = 1.1;
vector<Field> message;
message.push_back(field1);
message.push_back(field2);

这是我第一次发布堆栈溢出,所以我为任何错误的格式或问题歧义道歉。

不完全是。问题是,当我们在向量上迭代时

for (...:iteraor e....) {
   e->m_Message.actualValue;
}

actualValue的类型是什么?你可能会说每次都不同,但C++并不是这样工作的,代码中的每个表达式都有1种类型。(除了模板,但这基本上只是为你输入的每种类型提供一份新的代码副本)

您可以为所有Field的然后但引用(但不能复制到向量中)创建基类。

class FieldBase {
    public:
        CString name;
        bool state;
};
template<typename T>
class Field public: FieldBase
{
 public:
   T actualValue;
};
vector<FieldBase*> m_Message;

然后你需要一些信息来传达你正在处理的信息。可能是重载方法。

每个实例化的模板类都有不同的数据类型。在声明向量时,Field应该已经定义了数据类型,但这里没有。

我想,你要找的是一个变体类。像Qt这样的一些库提供变体,例如QVariant。

然而,变体本身不是模板类,也不可能是。变体类通常使用并集和void指针来实现。它是动态类型行为的实现。该类型在运行时是动态的。相比之下,模板在运行时不是动态的。类型是在编译时确定的,否则编译器要么停止,要么没有生成代码。

最重要的是,您的示例代码是错误的。正确的版本将是

Field<int> field1 = Field<int>();
field1.actualValue = 1;
Field<double> field2 = Field<double>();
field2.actualValue = 1.1;

这是而不是Java,不是吗?


首先,您应该知道Field<int>Field<double>不同的类型。看看你的例子。

template <typename T> class Field { ... };
Field<int> field1 = Field<int>();
field1.actualValue = 1;
Field<double> field2 = Field<double>();
field2.actualValue = 1.1;

编译器可能会这样想:

class Field_int { /* int version of Field */ };
Field_int field1 = Field_int();
field1.actualValue = 1;
class Field_double { /* double version of Field */ };
Field_double field1 = Field_double();
field1.actualValue = 1;

这就是模板实例化的工作方式-编译时。当编译器满足Field<int>时,它会根据模板代码创建一个新类

现在您正在尝试将不同版本的Field推送到vector中。

vector<???> message;
message.push_back(field1);
message.push_back(field2);

如您所知,vector可以容纳相同类型的数组。CCD_ 7和CCD_。


那么,怎么做呢?由于C++的模板是在编译时运行的,所以我们遇到了这个问题。那么,在运行时期间执行该操作如何?

我建议你使用Boost.Any。它可以在运行时更改其类型,所以我们可以使用它而不是模板。

(如果你不知道Boost,看看吧,你会喜欢的。)

您可以制作Field::actualValue boost::any

#include <boost/any.hpp>
class Field
{
    CString name;
    bool state;
    boost::any actualValue;
};
vector<Field> messages;
Field field1;
field1.actualValue = 1;
messages.push_back(field1);
Field field2;
field1.actualValue = 1.1;
messages.push_back(field2);

有了足够的元编程,你几乎可以做任何事情。

在这种情况下,您可能需要查看boost::variant,它存储一组固定类型中的一个,并为您提供对它的类型安全访问。如果不能做到这一点,boost::any可以保存任何类型中的任何一个,只有当您知道存储在其中的确切类型时,您才能取出类型。

接下来,类型擦除/运行时概念的技术可以让你对类型抽象出一组有限的操作,并将其存储在任何等价的文件中,同时允许你对数据进行有限的操作。

可能更容易的方法是创建一个基类,将std::unique_ptr存储到其中,并存储派生实例。如果需要,可以使用动态强制转换来获取特定的子类型。

如果这些都不起作用,您可以始终运行脚本语言,并用该语言而不是C++编写代码。许多脚本语言可以嵌入到C++中,而严肃的应用程序经常使用这种嵌入的脚本语言。