0

I'm very confused why range-for uses a ref in my example?

#include <vector>
#include <unordered_map>
using namespace std;

int main()
{
    const unordered_map<char, string> d2c_map= { {'1', "abc"} };
    const string digits{"1"};
    vector<string> R;
        
    for(const auto c : d2c_map.at(digits[0])) {
        R.push_back(c); // <-------------------------???
    } 
    return 0;       
}

Error indicates that the type of c is const char&:

error: no matching function for call to 'std::vector<std::__cxx11::basic_string<char> >::push_back(const char&)'

Demo

A_P
  • 331
  • 3
  • 15
  • `R.emplace_back(1, c); ` – EOF Oct 15 '20 at 21:35
  • There are some other issues with this code as well. First, the character `'1'` has an integer value which is not `1`. You'll need to fix that; perhaps you want to map `{'1', "abc"}` or perhaps you want to say `d2c_map.at(digits[0] - '0')`. Second, your range-based for loop copies every element of the map as you iterate over it, but you don't need the copy. Instead of `for (const auto c : ...)`, write `for (const auto& c : ...)` – Justin Oct 15 '20 at 21:44
  • @Justin thank you for pointing out the error. However the question is still there "why is 'c' a const char &??? that's my question. – A_P Oct 15 '20 at 22:18
  • `auto` doesn't deduce to a reference type, so `const auto c` will not deduce to `const char &c` in your example, but to `const char c`. The `for` loop will use `const auto c = *iterator;` where `iterator` is a `std::string::iterator`, which returns `char&` when dereferenced, but that will not make `c` deduce to `char&` but to just `char`. There are only two `push_back()`'s available in your example: `R.push_back(const string&)` and `R.push_back(string&&)`, neither of which can be called with a single `char` as input, hence the error. Where the extra `&` comes from, who knows, compiler detail. – Remy Lebeau Oct 15 '20 at 22:45
  • As you are obviously interested about the internals: Have you actually checked the type of `c`, e.g using type traits and static asserts? I believe that the compiler just outputs a "wrong" error message because he tries to pass `c` as const lvalue reference first (or last). It does not really matter as oerload resolution failed and the printed message is thus ambigiuos. – Sebastian Hoffmann Oct 16 '20 at 00:04
  • @SebastianHoffmann as far as I know type_traits are used for querying template arguments. However, after following this https://stackoverflow.com/a/20170989/4611344 the type of c is indeed `const char`. – A_P Oct 16 '20 at 14:09
  • @A_P How you can do this with type traits: `std::cout << std::is_same_v` (or use static_assert), then check for the types you suspect. – Sebastian Hoffmann Oct 16 '20 at 14:20

1 Answers1

5

How to push each character of a string into a vector of strings?

This line is trying to add a char to a vector<string>:

R.push_back(c);

If you want to add a string constructed from the char, you can do:

R.push_back({c});
cigien
  • 57,834
  • 11
  • 73
  • 112