当前位置: 首页 > 知识库问答 >
问题:

正确使用C变量模板

周奇文
2023-03-14

我目前正在从事一个项目,该项目需要一个生成简单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){ }

G不喜欢:

对“void XMLGenerator::createXML”的未定义引用

为什么不调用第一个createXML方法?

另外,如果我的问题有一个更简单的解决方案,我会感兴趣的。


共有1个答案

廖臻
2023-03-14

这里是一个解决方案,转发声明很重要,请注意std::forward与通用引用结合使用

#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();
}

编辑:添加了参数计数和char const*的静态断言,以替代不必要的std::string构造。

 类似资料:
  • 我正试图在java(或一般情况下)中了解线程安全性。我有这个类(我希望符合POJO的定义),它还需要与JPA提供商兼容: 如代码中注释行所述,是否有必要将和定义为,并且块是否按其应有的方式使用?或者我应该只使用块,而不将和定义为?的不应与另一个错误匹配。 这个链接说 对于所有声明为volatile的变量(包括long和double变量),读写都是原子的 我是否应该理解通过setter/getter

  • 我正在尝试使用Spring-Boot,并想使用Thymeleaf作为我的模板引擎。出于某种原因,当我想在我的thymeleaf片段中使用模型变量时,代码完成无法正常工作。例如,我像这样定义我的一个片段: 当我现在想在某个表达式中使用adminViewDTO时,它可以工作,但当我想访问adminViewDTO的成员并用红色下划线时,IntelliJ无法识别它们。例如,当我这样做时: 然后一些对象被下

  • 问题内容: 我正在使用一个大约100 MB腌制的广播变量,与之近似: 在具有3个c3.2xlarge执行程序和m3.large驱动程序的群集上运行,并使用以下命令启动交互式会话: 在RDD中,如果我坚持对该广播变量的引用,则内存使用量将激增。对于100 MB变量的100个引用,即使将其复制100次,我也希望数据使用总量不超过10 GB(更不用说在3个节点上30 GB)。但是,运行以下测试时,我看到

  • template module在Ansible中非常常用,而它在使用的时候又没有显示的指定template文件中的值,所以有时候用户会对template文件中使用的变量感到困惑,所以在这里又重新强调下。 template变量的定义 在playbook中定义的变量,可以直接在template中使用,同时facts变量也可以直接在template中使用,当然也包含在inventory里面定义的host

  • 这可能是一个新问题,所以我会马上说出来。这是我第一次创建IDisposable类,我想确保我正确创建了我的类,正确调用了它,并正确处理了它。谢谢! 这就是我所说的。

  • 我有以下代码使用可变参数模板来调用std::async, 但我收到以下编译错误消息: 没有用于调用“async(std::launch,bool (TestChild:: 我认为这可能与我传递其他参数以及参数包的事实有关。任何人都知道这有什么问题,我应该做些什么来让它发挥作用?