I have a C++ object (boost::format) that has a str() function which returns an std::string.

So when I need a formatted C string, I need to write something like:

(boost::format("%1% %2%") % "1" % "2").str().c_str()

I find that rather verbose, and I need it a lot. I thought of creating a derived class which has an operator char* and would work like this (Ch = char or wchar_t):

operator Ch const* () const
{
    return str().c_str();
}

But of course, the string returned by str() is deallocated when the function returns, and no valid C string is returned.

Is there any kind of workaround?

The workaround needs to create a string that exists as long as the surrounding function call:

lib_function((boost::format("%1% %2%") % "1" % "2").str().c_str()); 
// can be deallocated here
有帮助吗?

解决方案

The most obvious solution is to define a type which contains the std::string, and converts implicitly to a char const*. Something like:

class ToPlainC
{
    std::string myValue
public:
    ToPlainC( boost::format const& fmt )
        : myValue( fmt.str() )
    {
    }
    operator char const*() const
    {
        return myValue.c_str();
    }
};

which could be used:

lib_function( ToPlainC( boost::format( "%1% %2%" ) % "1" % "2" ) );

Such implicit conversions are not usually a good idea, but if you document the class well, that it should only be used for this particular scenario, I think it would be acceptable.

EDIT:

It occurs to me that to encourage only using this class as a temporary, in this particular scenario, you could name it using the naming conventions you normally use for functions, and not those you use for classes; the user would then have the impression that he was using a function, and it would stick out like a sore thumb if he used it otherwise.

其他提示

Return an std::string on the stack. It's an extra copy, so it's a bad idea if performance is important, but it would work to eliminate most of the redundant typing.

You can define a structure like one shown below:

struct my_str
{
  const std::string &tmp;
  my_str(const boost::format &tmp) : tmp( tmp.str() ) {}
  operator const char *() const { return tmp.c_str(); }
};

And you can call it like

lib_function ( my_str(boost::format("%1% %2%") % "1" % "2") );

If you are worrying the reference would be dangling, read this article.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top