【问题标题】:Variable Argument List following 'const std::string&' messes up the stack'const std::string&' 后面的变量参数列表弄乱了堆栈
【发布时间】:2017-06-27 14:19:52
【问题描述】:

我有一个函数:std::string format(const std::string sformat, ...); 它基本上就像一个花哨的 sprintf()。

由于我经常调用该函数,因此我想将格式字符串作为引用传递:const std::string& sformat。 不幸的是 va_start() 似乎无法在堆栈上找到变量参数列表的正确位置。

如果我删除“&”,它会正常工作。

两个问题:答:我是否需要引用以防止在调用期间复制sformat,或者优化器是否足够聪明,只需执行传递引用在后台? B:我可以做些什么来防止格式字符串的值传递并且仍然不会混淆 va_start() ?

我的猜测是:指针传递。还是有更好的解决方案?

【问题讨论】:

  • "或者有更好的解决方案" 放弃可变参数包并开始使用可变参数模板怎么样?
  • 这都是非常特定于编译器的,所以你能告诉我们你正在使用什么编译器吗?它的什么版本?你的目标是什么系统?
  • en.cppreference.com/w/cpp/utility/variadic/va_start :如果 parm_n 声明为引用类型或与默认参数提升产生的类型不兼容的类型,则行为未定义。
  • 你试过 boost 格式吗?

标签: c++ c++11 pass-by-reference


【解决方案1】:
namespace details {
  std::string format(char const* sformat, ...) {
    // code
  }
}
template<class...Args>
std::string format(std::string const& str, Args const&... args) {
  return details::format( str.data(), args... );
}

作为奖励,我可以写一个to_pod 助手:

namespace details {
  std::string format(char const* sformat, ...) {
    // code
  }
}
template<class T>
T const& to_pod(T const& t){ return t; }
template<class Char, class Attribs>
Char const* to_pod( std::basic_string<Char, Attribs> const& str ) {
  return t.data();
}
template<class...Args>
std::string format(std::string const& str, Args const&... args) {
  return details::format( str.data(), to_pod(args)... );
}

现在我可以将std::strings 作为第一个参数之后的内容传递,它们会自动转换为指向其缓冲区的char const* 指针。

...

如果您没有 C++11 编译器(例如 MSVC 2010),最好的办法可能是编写重载。

std::string format(std::string const& str) {
  return details::format( str.data() );
}
template<class A0>
std::string format(std::string const& str, A0 const& a0) {
  return details::format( str.data(), to_pod(a0) );
}
template<class A0, class A1>
std::string format(std::string const& str, A0 const& a0, A1 const& a1) {
  return details::format( str.data(), to_pod(a0), to_pod(a1) );
}
// etc

您可能不需要超过 10 个参数。

【讨论】:

  • 我会将其标记为解决方案,因为它对于当前的编译器来说是一个很好的解决方案。
  • 补充我的最后一条评论:不幸的是,我必须使用的编译器不知道可变参数模板。所以,我想我会使用多个重载和/或传递指针。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-01
  • 1970-01-01
相关资源
最近更新 更多