'const std::string&' 之后的变量参数列表弄乱了堆栈
Variable Argument List following 'const std::string&' messes up the stack
我有一个函数:std::string format(const std::string sformat, ...);
它基本上像花哨的 sprintf() 一样工作。
因为我经常调用该函数,所以我想将格式字符串作为引用传递:const std::string& sformat
。
不幸的是 va_start() 似乎无法在堆栈中找到变量参数列表的正确位置。
如果我删除“&”,它就可以正常工作。
两个问题:A: 我什至需要参考以防止在调用期间复制 sformat
,还是优化器足够聪明,只在后台传递参考?
B: 我该怎么做才能防止格式字符串的按值传递并且仍然不会混淆 va_start() ?
我的猜测是:指针传递。或者有更好的解决方案吗?
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::string
s 作为传递给第一个参数的东西,它们会自动转换为 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 个参数。
我有一个函数:std::string format(const std::string sformat, ...);
它基本上像花哨的 sprintf() 一样工作。
因为我经常调用该函数,所以我想将格式字符串作为引用传递:const std::string& sformat
。
不幸的是 va_start() 似乎无法在堆栈中找到变量参数列表的正确位置。
如果我删除“&”,它就可以正常工作。
两个问题:A: 我什至需要参考以防止在调用期间复制 sformat
,还是优化器足够聪明,只在后台传递参考?
B: 我该怎么做才能防止格式字符串的按值传递并且仍然不会混淆 va_start() ?
我的猜测是:指针传递。或者有更好的解决方案吗?
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::string
s 作为传递给第一个参数的东西,它们会自动转换为 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 个参数。