Why does C ++ accumulate the third argument

I write the following codes in my editor, but it cannot be compiled, it warns:

cannot convert 'std::basic_string<char, std::char_traits<char>, std::allocator<char> to 'const char*' in assignment| ||=== Build finished: 1 errors, 0 warnings ===| 

code:

 #include <iostream> //#inclide <algorithm> #include <numeric> #include <vector> using namespace std; int main() { std::vector<std::string> v; v.push_back(string("a")); v.push_back(string("b")); v.push_back(string("c")); string num = accumulate(v.begin(),v.end(),""); std::cout << num; return 0; } 

I don’t know why it cannot be compiled, please help me. Thanks:)

+4
source share
4 answers

Clause 26.7.2 / 1 of the C ++ 11 standard states:

 template <class InputIterator, class T> T accumulate(InputIterator first, InputIterator last, T init); 

[...]

1 Effects: calculates its result by initializing the accumulator acc with the initial value init, and then changing it with acc = acc + *i [...] for each iterator i in the range [first,last) in order.

[...]

String literals are of type const char[] , decaying to const char* when you pass them to functions. Therefore, the initializer that you pass to accumulate() will be const char* , and T will be const char* .

This means that acc from the above expression will be const char* , and *i will be string . This means that the following will not compile:

 acc = acc + *i; 

Because acc + *i gives std::string , and on the left side of the job you have const char* .

Like others, you must do:

  string num = accumulate(v.begin(),v.end(),string()); 

In addition, you do not need to do:

 v.push_back(string("a")); 

When inserting strings into a vector. It's enough:

 v.push_back("a"); 

An std::string will be implicitly constructed from the string literal "a" .

+6
source

One of the parameters of the std::accumulate template is the type of the return value, which will be deduced from the third argument of the function. This is also the type that should be able to accumulate values ​​in the input range of iterators. In your case, your return type should be std::string , but you pass "" , which is const char[2] . This is not a type that can be copied and used for accumulation.

You can fix this by passing std::string :

 string num = accumulate(v.begin(),v.end(), std::string()); 
+4
source

Instead of "" as the third argument, explicitly call std::string() :

 string num = accumulate(v.begin(),v.end(),std::string()); 
+1
source

The return type std::accumulate matches the type of the third parameter, which is output to const char* in your case (because you are passing a string literal).

This means that the function expects to work with const char* internally, but the iterator range contains std::string s, therefore barfs. This is why you must pass the correct type ( std::string ) in the third argument:

 string num = accumulate(v.begin(), v.end(), std::string()); 
0
source

Source: https://habr.com/ru/post/1483759/


All Articles