2013-07-12 61 views
5

我使用xsd从xml模式文件创建C++代码。对于一个xml类型,创建多个函数(用于序列化等)。
如果类型被称为XmlType将创建下列形式的多种功能:具有相同名称但参数类型不同的多个函数作为模板参数

XmlType XmlType_(const XmlType& a, const string& b) 
string XmlType_(const XmlType& a) 
... 

这是正常的功能,而不是XmlType将的成员,它们都具有相同的名称。 对于XmlType2该功能将被称为XmlType2_

我想为我的xml方案的所有不同的xml类型编写一个实用程序模板类。不同的功能将被称为洞察这个类。我到目前为止是这样的:

XmlUtil<XmlType, XmlType_, XmlType_> util; 

这感觉有点多余的,会变得更糟:

template<typename T> 
using TFunc1 = T (*)(const T&, const string&); 
template<typename T> 
using TFunc2 = string (*)(const T&); 

template<typename T, TFunc1<T> func2, TFunc2<T> func2> 
class XmlUtil { 
... 
}; 

当如果必须这样做,这样创建XmlUtil类的一个实例,当我必须通过更多的功能作为参数。

我想使用的Util类是这样的:

XmlUtil<XmlType, XmlType_> util; 

甚至更​​好这样

XmlUtil<XmlType> util; 

我能想到的就是以某种方式使用所定义的唯一途径,但它不感觉不错。
有没有其他的方法来做到这一点?

编辑: 我现在使用一个定义:

#define TRPL(name) name, name ## _, name ## _ 
... 
XmlUtil<TRPL(XmlType)> util; 

我将修改这一点,如果我找到一个更好的(也许覆盖套像Yakk在他的回答提出)。

+0

这是C++ 11特有的,我相信吗? –

+0

是的,我使用的是C++ 11(MinGW和gcc 4.8)。添加了标签。 – guini

+0

模板专业化。在C++中使用它进行等效的Func <>(在c#中),其中Execute具有模板参数特定实现和参数计数。通过使用模板中的默认设置,您可以选择仅定义一些类型参数。 –

回答

3

此:

XmlUtil<XmlType> util; 

是不可能的,因为没有办法摆脱XmlTypeXmlType_。在自动代码生成器之后它们的关系被丢弃。

然而这样的:

XmlUtil<XmlType_> util; 

是可能的。您可以推导出XmlType_的函数类型,然后使用推导的返回类型,即XmlType。我相信有这个目的的标准库函数。

对于两个不同的过载,这可能是棘手。我不认为你可以传递一个函数重载集合作为模板参数,解析是在模板参数的上下文中对一个函数的模板参数完成的。如果不使用预处理器,我认为没有办法推迟这个操作。

所以我认为你应该使用#define。这总比没有好。

0

类定义中的默认模板参数?

template<typename T, TFunc1<T> func1 = XmlType_, TFunc2<T> func2 = XmlType_> 
class XmlUtil { 
    // ... 
}; 
+0

函数的名称取决于类型名称。所以我认为这是行不通的。我编辑了这个问题,使之更清晰。 – guini

+1

@guini我只是试了一下,[它似乎编译正常](http://ideone.com/fu5s8M)。值得一试? –

+0

如果我理解正确,函数名称XmlType_在您的示例中已修复。但在我的情况下,函数名称会改变。如果我有类型Type1,函数将被称为Type1_,对于Type2它将被称为Type2_等。 – guini

0

您可以使用一个特质类这样

template <typename T> 
struct Trait{ 
    typedef T type; 
    typedef T (*func1)(const T&, const string&); 
    typedef string (*func2)(const T&); 
}; 

,使类XmlUtil有一个模板参数(我们将其命名为性状),并使用特质::类型,特质:: func1和Trait :: func2。完整使用请参见here

在这个例子中,XmlUtil的类型是这样:

XmlUtil<Trait<XmlType> > 

我已经这样做了,因为我不熟悉你的问题。这可能是你可以定义特质类右转入XmlUtil和使用

XmlUtil<XmlType> 

其他变化是可能的,它只是取决于你需要什么样的情况。

你可以阅读一个非常简短的介绍特质类​​。如果你想阅读更多关于这个话题,我建议你现代C++(Alexandrescu)。

+0

感谢您的回答。我会检查出来的。但我需要一些时间来了解它:-) – guini

+0

我改变了代码链接,我在那里写了一些评论 –

+0

重新阅读问题和答案我不确定我是否正确地解决了您的问题,请给我一些反馈意见如果需要,我可以提供更多的帮助。 –

0

我不知道我完全理解你的要求。序列化和反序列化的常用方法是创建工厂(抽象工厂)并动态地解析对象的构造。请注意,对于复杂结构,这可以得到改进,其中代码生成器可以创建成员函数来提取每个成员的确切类型。

但同样,我不完全理解你真正想做...作为一个建议,我相信,如果你提供了更多的解决问题的说明,它会有所帮助,因为这个问题集中在如何让你的解决方案发挥作用,并隐含地抛弃其他可能更好的设计方法。

1

这看起来像是覆盖集的作业。 foo_override_set_type类型的

static struct foo_override_set_type { 
    template<typename... Args> 
    auto operator()(Args...&& args) const 
    -> 
    decltype(foo(std::forward<Args>(args)...)) 
    { return (foo(std::forward<Args>(args)...)); } 
    template<typename T> 
    operator T() { return foo; } 
} foo_override_set; 

对象代表整个手柄组foo的。使用operator()调用它们会对foo执行覆盖设置查找并调用结果函数。将它们转换为函数指针与将代码foo转换为函数指针(或其他值)的做法相同。

你的代码生成可以自动生成这样的覆写集类型。它还可以制作一个特征类,通过专业化从XmlType类型映射到覆盖集XmlType_函数。

然后,您的XmlUtil<XmlType>可以通过该特征类访问覆盖集XmlType_。它首先实例化override设置变量,然后调用()

另外,@Xeo有一个建议,即创建这样的对象,就像在C++ 1y或C++ 1z中输入[]XmlType_一样简单。

+0

感谢您的建议。我还没有完全理解它,但我会研究它。你可能有一个关于覆盖集的文档的链接? – guini

+1

@guini不,不是真的。覆盖集只是一个对象,它的行为“好像”是一个语法上某个函数名称的完全重写集合。你可以用完美的转发和一个'template operator T'来做到这一点。你可以阅读完美的转发(我在上面的'operator()'中使用的C++ 11技术),这可以使它更有意义。 'operator T'存在,所以你可以给函数指针分配一个覆盖集,并让它“神奇地”提取属性覆盖。而且因为它是一个无状态的对象,所以可以将它或它的类型传递到你需要的地方。 – Yakk

相关问题