The asdas
is not a std::string
, rather a string literal which can referred as const char*
. That is why a.test("asd")
was not calling the member void test(std::string const& s)
.
How to achieve this?
One way to fix is proving one more member overload
class A
{
public:
// ... code
void test(std::string const& s) {
cout << "test " << s << endl;
}
void test(const char* s) { // overload for string literals
test(std::string{s});
}
};
See a demo
Alternatively, in c++11 you can SFINAE the two functions
class A
{
public:
template <typename T>
auto test(const T& t) // T can not be convertible to std::string
-> typename std::enable_if<!std::is_convertible<T, std::string>::value>::type
{
std::cout << "template " << t << std::endl;
}
template<typename T>
auto test(T const& s) // T can be convertible to std::string
-> typename std::enable_if<std::is_convertible<T, std::string>::value>::type
{
std::cout << "test " << s << std::endl;
}
};
See a demo
However, if you are able to at-least upgrade to c++14, you could use a string literal, and pass the std::string
to the void test(std::string const& s)
(i.e. no more member overloads required)
using namespace std::string_literals;
a.test("asd"s);
// ^^^
See a demo
One step up, in c++17 we can decide what part of condition to be compiled/ discarded at compile time using if constexpr
.
class A
{
public:
template <typename T>
void test(const T& t)
{
if constexpr (!std::is_convertible_v<T, std::string>)
{
std::cout << "template " << t << std::endl;
}
else
{
std::cout << "test " << t << std::endl;
}
}
};
See a demo
Also have a read: