Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot deduce template arguments for basic_string

Tags:

c++

templates

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.

like image 704
Carlos Brito Avatar asked Nov 29 '25 21:11

Carlos Brito


2 Answers

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

like image 171
Vittorio Romeo Avatar answered Dec 01 '25 11:12

Vittorio Romeo


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);
like image 38
Pete Becker Avatar answered Dec 01 '25 10:12

Pete Becker



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!