-2

I couldnt find any solution, so Im posting a new topic. I have to use accumulate with a const function as a parameter (doing some practice for a test):

  1. get_skills() - returns a list of skills and is defined as:

    const vector<string>& get_skills() const;
    
  2. I have to return a sum of the lengths of all skills

What I have tried:

double sum1 = accumulate(tmpObj.get_skills().begin(), tmpObj.get_skills().end(), 0., [](const string& s, const double& sum){return s.size() + sum;});

and I and up with:

 no matching function for call to object of type lambda
 note: candidate function not viable: no known conversion from 'double' to 'const std::__cxx11::string' (aka 'const basic_string<char>') for 1st argument

could somebody please explain what to use as lambda (I tried with tmpObj& but didnt change anything) and what is causing the "no known conversion from 'double' to 'const std::__cxx11::string'

thank you in advance!

  • Look at [accumulate](https://en.cppreference.com/w/cpp/algorithm/accumulate), especially the prerequisites for `BinaryOperation op`. – Olaf Dietsche Mar 27 '21 at 11:29
  • Aren't the examples in the [reference documentation](https://en.cppreference.com/w/cpp/algorithm/accumulate) clear enough? What in particular are you missing there? It seems that you misunderstood something about how you should use `std::accumulate()` you can't add `string`'s with `double`s. – πάντα ῥεῖ Mar 27 '21 at 11:30
  • @πάνταῥεῖ I couldnt solve it using the refference documentation. What I dont get is, what should I add into []. and also I made a typo when using s.size(). Im trying to add s.length() to the sum, so Im not really adding a string to a double – Akastil Mar 27 '21 at 11:35

2 Answers2

0

Without playing around with views you could just transform to string lengths first and then accumulate. Views would be nicer but this is pretty straightforward.

#include <string>
#include <iostream>
#include <numeric>
#include <vector>
#include <algorithm>


int main(int, char**)
{
    std::vector<std::string> skills = { "a", "ab", "abc" };
    std::vector<std::size_t> lengths;

    // transform to string lengths first
    std::transform(
            skills.begin(),
            skills.end(),
            std::back_inserter(lengths),
            [](const std::string& s){ return s.size(); }
    );

    // then accululate
    std::size_t sum = std::accumulate(lengths.begin(), lengths.end(), 0);
    std::cout << "sum = " << sum << '\n';

    return 0;
}

p.s. I should add that if doing this you may as well just do it manually but I wanted to give an example with acculate as per question.

systemcpro
  • 856
  • 1
  • 7
  • 15
-1

When you compare

double sum1 = std::accumulate(tmpObj.get_skills().begin(), tmpObj.get_skills().end(), 0.,
                              [](const string &s, const double &sum)
                                  { return s.size() + sum; });

with std::accumulate - Parameters

op - ...
Ret fun(const Type1 &a, const Type2 &b);

and

Type1 - T
Type2 - iterator


You can see, that the first argument to the binary operator must correspond to the return type (double, sum), and the second operator the type of the container (std::string), e.g.

[](double sum, const std::string &s) { return sum + s.size(); }

This is also why the compiler complains about

no known conversion from 'double' to 'const std::__cxx11::string'

It cannot convert the sum, a double, to the first argument of the lambda, a string.

Olaf Dietsche
  • 72,253
  • 8
  • 102
  • 198
  • I think your signature for `[](const string &s, const double &sum) { ... }` is incorrect. Should it be: `[](const double &sum, const string &s) { ... }`? – Chris Happy Nov 10 '22 at 01:34
  • @ChrisHappy at the beginning, I copied the code verbatim from the question for illustration. When you look at the second section, you will see the fixed version and explanation, why the change is necessary. – Olaf Dietsche Nov 10 '22 at 11:33