After a bit more of research, the best option imo is to use the C++17 feature std::basic_string_view
:
template<typename CharT>
void foo(std::basic_string_view<CharT> str)
{
(void)str; // do something with str ...
// while remembering that string_view does not own the string
}
So forget about the older explanation below if you have access to a C++17-compiler.
There are two cases here to consider. The first case is that you do not really want to do something special with the basic string, but rather you apply only methods also available for the char
-array (and just want to make sure it's called correctly regardless of the parameters). In this case, I'd simply use a general template parameter:
template<typename string_type
/* possibly some SFINAE to allow/disallow certain types */>
auto foo(string_type s)
{
std::cout << s << std::endl;
}
Second case is that you really want to do some special operation on the string which is not present for the char array. In this case you need an overload for basic_string
, but you probably want to write it only once and not for each and every function you use. This is what the following string_invoker
class tries to do (but it still needs some improvement, just working on it):
template<typename method>
struct string_invoker_impl
{
string_invoker_impl(method m) : m(m) {}
template<typename CharT>
auto operator()(std::basic_string<CharT> str) const
{
return m(str);
}
template<typename CharT>
auto operator()(CharT const * arr) const
{
return operator()(std::basic_string<CharT>{arr});
}
//possibly further methods for non-const array's, modification, etc.
method m;
};
auto string_invoker = [](auto m) { return string_invoker_impl<decltype(m)>{m}; };
auto foo_impl = [](auto str) {std::cout<< str <<std::endl; };
auto foo = string_invoker(foo_impl);
//you can merge the previous two calls also in a single one:
//auto foo = string_invoker( [](auto str) {std::cout<< str <<std::endl; });
int main(void)
{
foo("hello");
foo(std::string{ "hello" });
//foo(L"hello"); //need std::wcout, thus it fails with std::cout
//but it's no general problem, just overload your foo_impl function
//foo(std::wstring{ L"hello" });
}
DEMO