C++ 是否可以创建一个包含三种数据类型之一的容器,并且可以通过单个接口进行查询?
我有一个容器对象,它包含int、float或string。我有一个以类似方式处理的容器队列。目前,对于不同的数据类型,我有不同的getter。考虑到每个容器实例一次只包含一种数据类型,这并不是特别优雅C++ 是否可以创建一个包含三种数据类型之一的容器,并且可以通过单个接口进行查询?,c++,boost,C++,Boost,我有一个容器对象,它包含int、float或string。我有一个以类似方式处理的容器队列。目前,对于不同的数据类型,我有不同的getter。考虑到每个容器实例一次只包含一种数据类型,这并不是特别优雅 class MyContainer { MyContainer(float value); MyContainer(int value); MyContainer(string value); int getIntValue(); float getFlo
class MyContainer
{
MyContainer(float value);
MyContainer(int value);
MyContainer(string value);
int getIntValue();
float getFloatValue();
string getStringValue();
}
void processContainer(MyContainer& container)
{
// the following will not work, but is desired:
process(container->getValue()); // compilation error
}
void process(int value) {}
void process(float value) {}
void process(string value) {}
有没有一种方法可以利用上面的process方法的参数重载?例如,通过某种方式,我可以简单地调用process(container->getValue())?您可以使用模板和traits将模板化代码限制为string、float、int类型。如果您提前知道每个值的类型,那么A
union
可能会起作用。如果您可以使用Qt库,则是一个选项。问题在于知道应该由processContainer
从MyContainer
中选择哪个值。由于这些知识被封装在MyContainer中,因此流程调用可能也应该如此,或者至少是对它的分派。即:
class MyContainer
{
MyContainer(float value);
MyContainer(int value);
MyContainer(string value);
invokeProcess()
{
// call correct overload of process based on value stored
}
int getIntValue();
float getFloatValue();
string getStringValue();
}
void processContainer(MyContainer& container)
{
container->invokeProcess();
}
您还可以使用多态性和MyContainer的几个子类来实现这一点。基本上,您可以将转换逻辑从invokeProcess内部的case语句转换为外部的虚拟函数查找
其他人提到了工会。您确实需要一个有区别的并集,包括一个枚举来知道值是什么类型。不幸的是,可能不是,至少不是以任何优雅的方式。C++不允许只在返回类型上不同的重载函数,所以每个数据类型都必须有一个吸气剂。您可以有三个名为相同的函数,它们接受您想要返回的类型的伪变量,或者以指针作为参数并以这种方式返回值,但是如果我正确理解您的目的,那么这两个选项都不能使您更接近
进程(container->getValue())
,您想让MyContainer保存int、float或string
在这种情况下,您肯定需要模板来定义类:
template<typename T>
class MyContainer
{
private:
T _value;
MyContainer(T value)
{
_value = value;
}
public:
T GetValue()
{
return _value;
}
}
另一种方法是使用
Visitor
模式。这允许您根据类型动态地进行分派
struct Float;
struct Integer;
struct ContainerVisitor {
virtual void visit(Float& value) = 0;
virtual void visit(Integer& value) = 0;
// etc.
};
struct Container {
virtual void accept(ContainerVisitor& visitor) = 0;
};
struct Integer : Container{
virtual void accept(ContainerVisitor& visitor) {
visitor.visit(*this);
}
};
struct Float : Container{
virtual void accept(ContainerVisitor& visitor) {
visitor.visit(*this);
}
};
然后,无论您希望执行什么操作,都将其放入从ContainerVisitor
派生的类中:
struct Processor : ContainerVisitor {
virtual void visit(Float& value) {
// equivalent of your process(float);
}
virtual void visit(Integer& value) {
// equivalent of your process(int);
}
};
用法如下:
int main() {
Processor processor;
Integer i;
Float f;
i.accept(processor);
f.accept(processor);
}
假设每个容器实例一次只保存一种数据类型
:使用union如何?如果每个容器只保存一种数据类型,为什么不将容器作为模板?std::string不能包含在union中。我可以封装整数和浮点,但这并不能解决我的问题(只会节省我一个字节)。我想知道,process
为什么不是MyContainer
的成员?boost::variant
!这是一个已解决的问题。现在没有时间正确回答,但您正在搜索的是静态访问者
。这是一个非常好且优雅的解决方案
struct Processor : ContainerVisitor {
virtual void visit(Float& value) {
// equivalent of your process(float);
}
virtual void visit(Integer& value) {
// equivalent of your process(int);
}
};
int main() {
Processor processor;
Integer i;
Float f;
i.accept(processor);
f.accept(processor);
}