C++ 获取C++;可变模板右

C++ 获取C++;可变模板右,c++,c++11,variadic-templates,C++,C++11,Variadic Templates,我目前正在从事一个项目,该项目需要一个生成简单XML的对象。我对XML很陌生,仍然在学习C++。 我试图实现的是一个函数,可以在代码中这样调用: std::string xml = createXML("name", "attribute1", 10, "attribute2", "stringForAttrib2"); 在这一行之后,xml字符串应该包含如下内容: 函数必须接受所需的任意多个属性,并且名称不是可选的。 我试过这样的方法:

我目前正在从事一个项目,该项目需要一个生成简单XML的对象。我对XML很陌生,仍然在学习C++。 我试图实现的是一个函数,可以在代码中这样调用:

std::string xml = createXML("name", "attribute1", 10, "attribute2",
                            "stringForAttrib2");
在这一行之后,
xml
字符串应该包含如下内容:

函数必须接受所需的任意多个属性,并且名称不是可选的。 我试过这样的方法:

template<typename ...Attributes>
void XMLGenerator::createXML(std::string param_name, Attributes... attributes)
{
    std::ostringstream xmlString;
    xmlString << "<parameter name=\"" << param_name << "\" ";
    createXML(xmlString, attributes...);
    xmlString << "/>";
    m_xmlString << xmlString;
}

template<typename ...Attributes, typename DataType>
void XMLGenerator::createXML(std::ostringstream &xmlString,
                             std::string attribut_name, DataType data,
                             Attributes... attributes)
{
    xmlString << attribut_name << "=\"" << data << "\" ";
    createXML(xmlString, attributes...);
}

void XMLGenerator::addParameter(std::ostringstream &xmlString){ }
模板
void XMLGenerator::createXML(标准::字符串参数名称、属性…属性)
{
std::ostringstreamxmlstring;
这里,forward声明很重要,注意std::forward与通用引用Ts&&:

#include <iostream>
#include <string>

// =================================
// print_attribs parameter usage : ( os, name0, val0, ..., nameN, valN )
// name is char const* or std::string
// val can be anything compatible with os operator<<
// print_attribs is specialize for char const* and std::string values to enclose them with double quotes.

template < typename T, typename... Ts> void print_attribs( std::ostream & os, char const * name, T&& val, Ts&&... ts );
template < typename... Ts>             void print_attribs( std::ostream & os, char const * name, char const * val, Ts&&... ts );
template < typename... Ts>             void print_attribs( std::ostream & os, char const * name, std::string const & val, Ts&&... ts );

template < typename T, typename... Ts> void print_attribs( std::ostream & os, std::string const & name, T&& val, Ts&&... ts );
template < typename... Ts>             void print_attribs( std::ostream & os, std::string const & name, char const * val, Ts&&... ts );
template < typename... Ts>             void print_attribs( std::ostream & os, std::string const & name, std::string const & val, Ts&&... ts );

void print_attribs( std::ostream & os ) { }

template < typename... Ts>
void print_attribs( std::ostream & os, char const * name, char const * val, Ts&&... ts ) { 
    os << " " << name << "=\"" << val << "\"";
    print_attribs( os, std::forward<Ts>(ts)... );
}

template < typename... Ts>
void print_attribs( std::ostream & os, std::string const & name, char const * val, Ts&&... ts ) { 
    print_attribs( os, name.c_str(), val, std::forward<Ts>(ts)... );
}

template < typename... Ts>
void print_attribs( std::ostream & os, char const * name, std::string const & val, Ts&&... ts ) { 
    os << " " << name << "=\"" << val << "\"";
    print_attribs( os, std::forward<Ts>(ts)... );
}

template < typename... Ts>
void print_attribs( std::ostream & os, std::string const & name, std::string const & val, Ts&&... ts ) { 
    print_attribs( os, name.c_str(), val, std::forward<Ts>(ts)... );
}

template < typename T, typename... Ts>
void print_attribs( std::ostream & os, char const * name, T&& val, Ts&&... ts ) { 
    os << " " << name << "=" << std::forward<T>(val);
    print_attribs( os, std::forward<Ts>(ts)... );
}

template < typename T, typename... Ts>
void print_attribs( std::ostream & os, std::string const & name, T&& val, Ts&&... ts ) { 
    print_attribs( os, name.c_str(), std::forward<T>(val), std::forward<Ts>(ts)... );
}

template < typename... Ts>
void print( std::ostream & os, char const * name, Ts&&... ts ) {
    static_assert( sizeof...(ts) % 2 == 0, "arguments must be paired of string and value" );
    os << "<parameter name=\"" << name << "\"";
    print_attribs( os, std::forward<Ts>(ts)... );
    os << " />";
}

template < typename... Ts>
void print( std::ostream & os, std::string const & name, Ts&&... ts ) {
    static_assert( sizeof...(Ts) % 2 == 0, "Ts must be even, as they are pairs of name and value" );
    print( os, name.c_str(), std::forward<Ts>(ts)... );
}

int main() {
    auto endl = [] { std::cout << std::endl; };
    print( std::cout, "example", "foo", 10 ); endl();
    print( std::cout, "example", "foo", 10, "bar", "bare" ); endl();
    print( std::cout, "example", "foo", 10, "bar", 3.14f ); endl();
    print( std::cout, "example", "foo", 10, "bar", 3.14f, "bar", 3.14f ); endl();
    print( std::cout, "example", "foo", 10, "bar", "bare", "baz", 3.14f ); endl();
}
#包括
#包括
// =================================
//print_attribs参数用法:(os,name0,val0,…,nameN,valN)
//名称为char const*或std::string
//val可以是与os运算符void print_attribs兼容的任何内容(std::ostream&os,char const*name,T&&val,Ts&&Ts);
模板无效打印属性(std::ostream&os,char const*name,char const*val,Ts&…Ts);
模板无效打印属性(std::ostream&os,char const*name,std::string const&val,Ts&&…Ts);
模板无效打印属性(std::ostream&os,std::string const&name,T&&val,Ts&&Ts);
模板无效打印属性(std::ostream&os,std::string const&name,char const*val,Ts&&Ts);
模板无效打印属性(std::ostream&os,std::string const&name,std::string const&val,Ts&&Ts);
无效打印属性(std::ostream&os){}
模板
无效打印属性(std::ostream&os,char const*name,char const*val,Ts&&…Ts){

os g++的消息表明确实调用(使用)了第一个函数模板,但出现了链接器错误。您是否将所有模板代码都放在头文件中了?没有!忘记了这一点,只是修改了代码,现在我得到了:XMLGenerator::createXML(std::basic_ostringstream&)的多个定义'我修复了前面的问题。现在我让它运行,但得到了一个segfault。我想在这一点上,我需要一个/更多的信息。这个接口有点奇怪,你不觉得吗?传入属性名和值都混在一起了…我建议你引入一个
模板结构xmltribute{std::string name;t value;}
元素,并将其用作变量调用的参数。这似乎是我想要的,但我需要一点时间来正确理解它。谢谢!这可能是一个愚蠢的问题,但有没有一种方法可以使用您的解决方案,而不必每次都指定“ostream”?因此用户只写“print”(“example”,“foo”,10);”