简体   繁体   中英

Variable Argument List following 'const std::string&' messes up the stack

I have a function: std::string format(const std::string sformat, ...); It basically works like a fancy sprintf().

Since I call that function a lot I wanted to pass the format string as a ref: const std::string& sformat . Unfortunately va_start() seems to have problems finding the right spot on the stack to the variable argument list.

If I remove the '&' it works fine.

Two questions: A: Do I even need the reference in order to prevent a copy of sformat during the call, or is the optimizer clever enough to just do a pass-by-ref in the background? B: What can I do to prevent a pass-by-value of the format string and still don't confuse va_start() ?

My guess is: pass-by-pointer. Or is there a better solution?

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... );
}

As a bonus, I can write a to_pod helper:

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)... );
}

and now I can pass std::string s as things past the first argument, and they are auto-converted to char const* pointers to their buffer.

...

If you do not have a C++11 compiler (say MSVC 2010), your best bet is probably to just write overloads.

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

You are probably not going to want more than 10 arguments.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM