Reputation: 9369
Consider the following example.
#include <string>
template<class CharT, class Traits = std::char_traits<CharT >, class Allocator = std::allocator<CharT >>
void f(const std::basic_string<CharT, Traits, Allocator>& s) {
}
int main() {
f("Hello World!");
}
When compiling it, I get
mismatched types
‘const std::basic_string<_CharT, _Traits, _Alloc>’ and ‘const char []’
Why cannot the compiler deduct "CharT" and do the conversion to the appropriate basic_string<>
? I'd like to have only one signature for f() valid for any argument type for which a conversion to a basic_string<>
exists, is there any solution for this problem?
Upvotes: 2
Views: 1971
Reputation: 275385
What you ask would require the compiler iterate over every basic_string<T>
until it determined that there was exactly one T
that matched. Alternatively, it could invert the possibly Turing complete process to figure out what the template
argument is. template
argument deduction like that is pattern matching: it takes the arguments, and matches it against your pattern, and deduces the types simply. If you want more, you need to tell it how to invert the mapping from CharT
to basic_string<CharT,A>
constructors. C++1y makes it a touch easier with concepts lite, but the kind of machinery you want still will not be there.
By far the easiest solution is to have two overloads for char
and wchar_t
basic_string
s (actual functions, not template
s), and then have them call a template
generic function like what you wrote passing in the CharT
explicitly.
Fancier would involve code that actually did the above inversion, where you might have it work from an acceptable set of strings, and check which the arguments can be constructed from, assert that there is only one option, and deduce CharT
that way. While fun, I doubt this is worth it.
Upvotes: 1
Reputation: 14174
You are passing a raw string to your function, which is not a std::string
, is a character array, a const char []
.
Even if std::string
has a constructor which gets a char array, implicit type conversions are not applied during template argumment deduction (Exactly the problem you have). See this thread for more information about the topic.
There are two possible solutions:
Pass a std::string
instead of a raw string to your function:
f( std::string( "hello" ) );
Write an overload of your function which works with raw strings:
template<typename CHAR_T , std::size_t LENGHT>
void f( const CHAR_T (&string)[LENGTH] )
{
f( std::string( string ) ); //Just wrap the call to not duplicate code.
}
Upvotes: 6
Reputation: 1758
This should do the trick.
You're specifying a char array to your function witch is supposed to get std::string. You need to use a constructor to convert these.
#include <string>
template<class CharT, class Traits = std::char_traits<CharT >, class Allocator = std::allocator<CharT >>
void f(const std::basic_string<CharT, Traits, Allocator>& s) {
}
int main() {
std::string str("Hello World!");
f(str);
}
Upvotes: 0