I have to write a library which contains a function that takes two strings parameters:
void foo(const std::string& arg1, const std::string& arg2);
My library is going to be used by some people that don't like C++ and are only used to const char*
.
To satisfy their likes, I changed the prototype:
void foo(const char* arg1, const char* arg2);
And made my first version a simple inline call:
inline void foo(const std::string& arg1, const std::string& arg2)
{
foo(arg1.c_str(), arg2.c_str());
}
Of course, thanks to the std::string
constructors, it would have worked almost the same way with just the first version. Writing this overload just avoids instanciating useless std::string
in the case someone passes only const char*
.
But now I wonder: is this overload really necessary or is it just premature optimization ?
Also, I'm feeling like this is somehow incomplete: should I write also void foo(const char* arg1, const std::string& arg2)
and void foo(const std::string& arg1, const char* arg2)
overloads ? What if I have 3, 4 or more (n
) parameters ? Should I write 2n overloads ?
In short, have you ever faced a similar situation ? What choices did you made and why ?
Thank you.
IMO it's reasonable to have two overloads to handle two different programming styles that co-exist within your organization.
Technically it's not just an optimization:
const char*
can be extern "C"
, so might be useful for bindings from other languages, or even from other C++ code across a dll boundary with incompatible standard library implementation.std::string
can throw bad_alloc
, so if it cannot otherwise fail then the const char*
version is useful if you have a C-style string and want to use it in a nothrow context.Also beware that in principle c_str()
can throw bad_alloc
, but I doubt that any implementations actually do.
2n overloads doesn't seem worthwhile to me - if someone is mixing string
and char*
then it's not just a programming style difference, they're actually using mixed formats for some reason. Since they're using both already, they can convert for themselves.
This all assumes that the function is simple enough that you're happy to implement the actual work with const char*
parameters. If the implementation based on string
would be significantly simpler (for example if it takes significant code to make it exception-safe otherwise), then that probably wins over efficiency anyway, so don't provide any overloads, let their const char*
convert to string
.
As long as you want to work with C++ (and not in C), the second one seems unneccessary, if you've this:
void foo(const std::string& arg1, const std::string& arg2);
You can call this with all combinations of std::string
and char*
as:
char *ca, *cb;
std::string sa, sb;
//...
foo(ca,cb); //char*, char*
foo(sa,cb); //std:string, char*
foo(sa,sb); //std::string, std::string
foo(ca,sb); //char*, std::string
If const char * text
is never null, you could use string
, because it has implictit constructor, so string
class version could be enough. In other hand: if const char * text
could be null, it generates runtime error.
One more thing: on DLL interface STL is not really good option. So if the function is part of a DLL interface, you may use C style strings.
I may do it in that way:
#include <string>
using namespace std;
void foo( const string arg0, const string arg1 )
extern "C" _declspec( dllexport ) void foo( const char * arg0, const char * arg1 )
{
string string_arg0, string_arg1;
if ( arg0 != 0 )
string_arg0 = arg0;
if ( arg1 != 0 )
string_arg1 = arg1;
foo(string_arg0, string_arg1);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With