I have this function definition in my code:
template <
class CharT,
class Traits = std::char_traits<CharT>,
class Allocator = std::allocator<CharT>
> std::basic_string<CharT, Traits, Allocator> bytes2string(const Bytes& bytes)
{
// do work ...
}
And when I try to call the function like this:
int main()
{
Bytes bytes{'H', 'e', 'l', 'l', 'o'};
std::string str = bytes2string(bytes); // error
return 0;
}
I am met with the following error:
error:
no matching function for call to 'bytes2string'
note:
candidate template ignored: couldn't infer template argument 'CharT'
> std::basic_string<CharT, Traits, Allocator> bytes2string(const Bytes& bytes)
I'm pretty sure it should work but alas, it doesn't. Also Bytes is just a std::vector<char> in case anyone wanted to know.
Look closely at your signature:
template <
class CharT,
class Traits = std::char_traits<CharT>,
class Allocator = std::allocator<CharT>
> std::basic_string<CharT, Traits, Allocator> bytes2string(const Bytes& bytes);
There's nothing that allows CharT to be deduced - it needs to be explicitly supplied by the user.
std::string str = bytes2string(bytes);
Unfortunately C++ doesn't have Hindley-Milner type inference - it is not possible to deduce template parameters of a return type in this way. Function template parameters can only be deduced via arguments passed to the function.
If you change your signature to:
template <
class CharT,
class Traits = std::char_traits<CharT>,
class Allocator = std::allocator<CharT>
> void bytes2string(std::basic_string<CharT, Traits, Allocator>& out, const Bytes& bytes);
And invoke:
std::string str;
bytes2string(str, bytes);
Your template parameters will be deduced.
live example on wandbox
If the function is supposed to return std::string, then write it that way:
std::string bytes2string(const Bytes& bytes);
If it's supposed to be able to produce arbitrary instantiations of std::basic_string then you need to supply the appropriate template arguments. Often that's done by passing in a string of the appropriate type. That doesn't seem appropriate here, since there is no obvious use for passing in a string other than to provide template arguments.
The alternative is to name the appropriate types at the point of the call:
std::string str = bytes2string<char>(bytes);
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