I have the following code:
// string specializations
void foo(const char *a, const char *b);
void foo(const char *a, const std::string &b);
void foo(const std::string &a, const char *b);
void foo(const std::string &a, const std::string &b);
// generic implementation
template<typename TA, typename TB>
void foo(TA a, TA b)
{...}
The problem is that this test case:
char test[] = "test";
foo("test", test);
ends up calling the templated version of foo
. Obviously, I can just add a few more overloads with various mixes of non-const
parameters, but I want to know: is there's a better way to overload foo
such that it is specialized on all const
and non-const
pairings of strings? One that doesn't require me to hope I haven't missed some permutation of argument types?
Overloading on the basis of const type can be useful when a function return reference or pointer. We can make one function const, that returns a const reference or const pointer, other non-const function, that returns non-const reference or pointer.
C++ allows member methods to be overloaded on the basis of const type. Overloading on the basis of const type can be useful when a function returns a reference or pointer.
Rules of Function Overloading in C++The functions must have the same name. The functions must have different types of parameters. The functions must have a different set of parameters. The functions must have a different sequence of parameters.
There are legitimate uses of having two member functions with the same name with one const and the other not, such as the begin and end iterator functions, which return non-const iterators on non-const objects, and const iterators on const objects, but if it's casting from const to do something, it smells like fish.
Thanks to Mooing Duck's suggestion, this is my solution:
// string specialization
void foo(const std::string &a, const std::string &b);
template<typename TA, typename TB>
typename std::enable_if<
std::is_constructible<std::string, TA>::value &&
std::is_constructible<std::string, TB>::value
>::type foo(TA a, TB b)
{
foo(std::string(std::move(a)), std::string(std::move(b)));
}
// generic implementation
template<typename TA, typename TB>
typename std::enable_if<
!std::is_constructible<std::string, TA>::value ||
!std::is_constructible<std::string, TB>::value
>::type foo(TA a, TB b)
{...}
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