C++访问者模式处理模板化字符串类型?
我正在尝试使用访问者模式来序列化对象的内容。然而,我遇到的一个障碍是当我访问字符串时。我的字符串是模板类型,类似于STL的basic_string。就像这样:
basic_string<char_type, memory_allocator, other_possible_stuff> \\ many variations possible!
由于我可以有很多不同的模板化字符串类型,所以我无法将它们添加到我的访问者界面中。这太荒谬了。但我无法将模板添加到 VisitString 方法中,因为 C++ 禁止在虚拟方法中使用模板参数。
那么我有什么选择来解决这个问题呢?
编辑:我添加了一些基本代码
class IVisitor
{
public:
virtual void VisitString(some_kind_of_string_type string) = 0; // this is what I want in theory
};
class MyObject
{
public:
typedef basic_string<char8, myAllocator, some_flag> MyStringType;
Accept(IVisitor* visitor)
{
visitor->VisitString(mString);
}
private:
MyStringType string;
};
class MyOtherObject
{
public:
typedef basic_string<char16, myOtherAllocator, some_other_flag> MyOtherStringType;
Accept(IVisitor* visitor)
{
visitor->VisitString(mString);
}
private:
MyOtherStringType string;
};
class Reader : public IVisitor
{
public:
virtual void VisitString(some_kind_of_string_type string)
{
// read some data, give it to the string
}
}
I'm trying to use the visitor pattern to serialize the contents of objects. However one snag I'm hitting is when I'm visiting strings. My strings are of a templated type, similar to STL's basic_string. So something like:
basic_string<char_type, memory_allocator, other_possible_stuff> \\ many variations possible!
Since I can have very many different templated string types, I can't go and add them to my visitor interface. It would be ridiculous. But I can't add templates to my VisitString method because C++ prevents using templates parameters in virtual methods.
So what are my options to work around this?
EDIT: I've added some basic code
class IVisitor
{
public:
virtual void VisitString(some_kind_of_string_type string) = 0; // this is what I want in theory
};
class MyObject
{
public:
typedef basic_string<char8, myAllocator, some_flag> MyStringType;
Accept(IVisitor* visitor)
{
visitor->VisitString(mString);
}
private:
MyStringType string;
};
class MyOtherObject
{
public:
typedef basic_string<char16, myOtherAllocator, some_other_flag> MyOtherStringType;
Accept(IVisitor* visitor)
{
visitor->VisitString(mString);
}
private:
MyOtherStringType string;
};
class Reader : public IVisitor
{
public:
virtual void VisitString(some_kind_of_string_type string)
{
// read some data, give it to the string
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
您需要运行时多态性吗?
[1] 中的调用可以使用访问者中最不专业的通用模板化
operator()
转换为v( o )
:但这可能会与其他访问者实现(例如,上面的访问者可以使用单个模板化方法来实现):
因此最终您将不得不以任何一种方式进行妥协。
这种方法类似于 boost::variant 访问者实现(您可能想看一下),不同之处在于 boost::variant 是单个类而不是层次结构。
Do you need runtime polymorphism?
The call in [1] can be converted into
v( o )
with a generic templatedoperator()
in the visitors that is the least specialized:But this can interfece with other visitor implementations (for example, the above visitor can be implemented with a single templated method):
So at the end you will have to compromise in either way.
This approach is similar to the boost::variant visitor implementation (you may want to take a look at it), with the difference that the boost::variant is a single class and not a hierarchy.
最后,我采取了稍微不同的方法。我不希望使用具有模板化方法的访问者(这当然是不可能的),而是决定将类似访问者的类作为模板参数传递给对象的访问方法。完全简化的示例:
使用此方法,我仍然可以使用模板化字符串,同时仍然能够将任何类型的“访问者”传递给我的对象。
In the end, I went with a slightly different approach. Instead of hoping to use a visitor with templated methods (which is, of course, impossible), I decided to pass a visitor-like class as a template parameter to my object's visit method. Totally simplified example:
With this method, I still get to use my templated strings while still being able to pass any kind of "visitor" to my objects.
您的访问者应该只处理字符串的基本表示(char* / wchar*);
然后由accept方法来处理转换。
your visitor should handle only a basic representation of strings (char* / wchar*);
it is then up to the accept method to process the cast.
好吧,问题是,字符串上的模板参数可能如此不同,您可以为它们应用一种单一的序列化方法吗?如果是这样,您可以编写一个具有模板化构造函数的适配器,该构造函数将序列化所需的所有信息提取为统一的表示形式。然后您使用适配器访问序列化器。
编辑:添加代码后,我仍然认为适配器可以解决您的问题,但反之亦然。在
Accept
方法中,构造一个本地适配器并将其传递给Visitor
。当Visitor
对其进行修改时,您可以在适配器上使用模板方法extractToString
将信息转换为特定的字符串版本。这可能会使适配器变得复杂,具体取决于必须处理的字符串模板实例化的不同程度。Well, the question is, of the template parameters on your string can be so different, can you apply one single serialization method for them? If so, you could write an adapter that has a templated constructor that extracts all the information needed for serialization into a uniform representation. Then you visit the serializer with the adapter.
EDIT: After you added you code, I still think that an adapter could solve your problem, only the other way around. In you
Accept
-method, construct a local adapter and pass it to theVisitor
. When theVisitor
has modified it, you can use a template methodextractToString
on the adapter that converts the information to a specific string version. This may make the adapter quit complex, depending on how different the string-template instantiations have to be handled.由于所有字符串类都是不同的类型,因此您需要某种程度的妥协(或者是一个通用的子类型,带有虚拟方法,用于您的字符串,或者是一个适配器,或者为每个不同的 向访客输入)。混合通用编程和面向对象可能会很痛苦,特别是如果您不接受妥协的话。
例如。
Since all your string classes are of different types, you will need some level of compromise (either a common sub-type, with virtual methods, for your strings, or an adapter, or adding a method for each different type to the visitor). Mixing generic-programming and oo can be a pain, especially if you don't accept compromises.
Eg.
也许您可以考虑下面的内容,但在这种情况下,您需要将访问者机制分离到不同的访问者类别。 WStringVisitor 和 StringVisitor 只是不同访问者语义的示例。
May be you can consider below, but in this case you need to separate visitor mechanisms to different visitor classes. WStringVisitor and StringVisitor are just examples for different Visitor semantics.
我认为这里的根本问题是访问者模式都是关于虚拟函数的,而您通过函数模板聚集字符串。而且这些不容易混合。事实上,我能想到的将两者混合的唯一方法是类型擦除。
如果您找不到使用此技术做您想做的事情的方法,我认为您不会找到方法。
I think the fundamental problem here is that the Visitor pattern is all about virtual functions, while you herd your strings through function templates. And these just don't easily mix. In fact, the only way I can think of to mix the two is type erasure.
If you don't find a way to do what you want using this technique, I don't think you'll find a way.