0

I am writing a simplified version of std::string. When i'm writing the free function, i use the for_each function like this:

void String::free()
{
    std::for_each(element, end, [this](char *c){ alloc.destroy(c); });
    alloc.deallocate(element, end-element);
}

This function will destory the char memory, and delete the memory space allocated by allocator. But it will be error when i compile it.

In file included from /usr/include/c++/9/algorithm:62,
                 from 13_44_String.cpp:2:
/usr/include/c++/9/bits/stl_algo.h: In instantiation of ‘_Funct std::for_each(_IIter, _IIter, _Funct) [with _IIter = char*; _Funct = String::free()::<lambda(char*)>]’:
13_44_String.cpp:20:69:   required from here
/usr/include/c++/9/bits/stl_algo.h:3876:5: error: no match for call to ‘(String::free()::<lambda(char*)>) (char&)’
 3876 |  __f(*__first);
      |  ~~~^~~~~~~~~~
13_44_String.cpp:20:33: note: candidate: ‘String::free()::<lambda(char*)>’ <near match>
   20 |     std::for_each(element, end, [this](char *c){ alloc.destroy(c); });
      |                                 ^
13_44_String.cpp:20:33: note:   conversion of argument 1 would be ill-formed:
In file included from /usr/include/c++/9/algorithm:62,
                 from 13_44_String.cpp:2:
/usr/include/c++/9/bits/stl_algo.h:3876:5: error: invalid conversion from ‘char’ to ‘char*’ [-fpermissive]
 3876 |  __f(*__first);
      |  ~~~^~~~~~~~~~
      |     |
      |     char

The right answer is change char * to char & like this:

void String::free()
{
    std::for_each(element, end, [this](char &c){ alloc.destroy(&c); });
    alloc.deallocate(element, end-element);
}

I do not know why i can't pass a char pointer to a lambda. Why i must use the &.

ciel
  • 33
  • 5
  • Because `std::for_each`, when calling the lambda, doesn't pass a pointer? For the same reason, `char c; lambda(c)` wouldn't work with your lambda. – HolyBlackCat Nov 13 '21 at 08:55
  • The error message contains all informations... you simply call a function with wrong parameter type. And why the interface is as it is can not be answered :-) – Klaus Nov 13 '21 at 08:56
  • @Klaus Sorry, I am a beginner of c++. I get it now. Thanks for your answer. – ciel Nov 13 '21 at 09:19
  • No problem :-) What I want to say: Read the error messages carefully! Even if it is a long list, especially if many template instantiations are involved, at the end you see most often a detailed reasoning. Another hint: If one compiler eg. gcc gives not a good error message, try some other compilers, like clang or whatever. Maybe the additional/different message is a bit more explanatory. – Klaus Nov 13 '21 at 09:24
  • Why would a `String` class need to allocate and free *individual characters*? Presumably `element` is a pointer to a single buffer of characters, so you should be able to just allocate and free the buffer as a whole, *accessing* individual characters when needed. – Remy Lebeau Nov 13 '21 at 19:19

1 Answers1

0

From std::for_each documentation:

template< class InputIt, class UnaryFunction >
UnaryFunction for_each( InputIt first, InputIt last, UnaryFunction f );

Applies the given function object f to the result of dereferencing every iterator in the range [first, last), in order.

Note the emphasis on result of dereferencing in the above quote. Now lets apply this quote to your 1st code snippet. In your case:

f is equivalent to the lambda that you supplied

result of dereferencing the iterator is char

So the parameter should be a char type. But you're supplying/specifying a char* so you get the mentioned error.

Now in your 2nd code snippet, you fixed this by specifying the parameter type in the lambda to be char& and so the code works.

Jason
  • 36,170
  • 5
  • 26
  • 60
  • You're welcome. Also, there are some errors in the book `C++ Primer by Lippman`. One such error can be found at: [C++ Primer Error](https://stackoverflow.com/questions/66515465/error-spotted-in-c-primer-5th-edition-shared-ptrint) – Jason Nov 13 '21 at 09:19