Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are these overloads necessary?

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.

like image 665
ereOn Avatar asked Jul 29 '11 08:07

ereOn


3 Answers

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:

  1. the 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.
  2. the conversion to 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.

like image 139
Steve Jessop Avatar answered Sep 29 '22 23:09

Steve Jessop


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
like image 29
Nawaz Avatar answered Sep 29 '22 21:09

Nawaz


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);
}
like image 34
Naszta Avatar answered Sep 29 '22 23:09

Naszta