The range library implementation of the copy algorithm [duplicate] - c++

This question already has an answer here:
Why is std::back_inserter_iterator not WeaklyIncrementable in RangeV3?
(1 answer)
Closed 2 years ago.
I am building some snippets that should work with both the C++20 Ranges library and the range-v3 library and I noticed some differences in the implementation of the copy algorithm.
The following code using C++20 ranges library (from the Standard Library), compiles with GCC 11 (and prints 1 2 3 4 5).
#include <iostream>
#include <vector>
#include <ranges>
#include <algorithm>
int main()
{
std::vector<int> arr {1, 2, 3, 4, 5};
std::ranges::copy(arr, std::ostream_iterator<int>(std::cout, " "));
}
Here is a link: https://wandbox.org/permlink/V13bdDoxSYjqDW3m
The same code, using the range-v3 library, fails to compile with VC++ 2019 16.5:
#include <iostream>
#include <vector>
#include "range/v3/algorithm/copy.hpp"
int main()
{
std::vector<int> arr {1, 2, 3, 4, 5};
ranges::copy(arr, std::ostream_iterator<int>(std::cout, " "));
}
With the following errors:
main.cpp(134,9): error C2672: 'operator __surrogate_func': no matching overloaded function found
main.cpp(134,59): error C7602: 'ranges::_copy::copy_fn::operator ()': the associated constraints are not satisfied
range-v3-master\include\range/v3/algorithm/copy.hpp(57): message : see declaration of 'ranges::_copy::copy_fn::operator ()'
main.cpp(134,59): error C2780: 'ranges::detail::in_out_result<I,O> ranges::_copy::copy_fn::operator ()(I,S,O) const': expects 3 arguments - 2 provided
range-v3-master\include\range/v3/algorithm/copy.hpp(45): message : see declaration of 'ranges::_copy::copy_fn::operator ()'
There is a unit test in the range-v3 library, which is very similar:
using namespace ranges;
std::ostringstream sout;
std::vector<int> copy_vec{1,1,1,1,1};
copy(copy_vec, ostream_iterator<>(sout, " "));
CHECK(sout.str() == "1 1 1 1 1 ");
If I try is with Compiler Explorer, it does not compile with any compiler (gcc, Clang, VC++). The gcc errors are:
note: candidate expects 1 argument, 2 provided
note: candidate expects 3 arguments, 2 provided
error: no match for call to '(const ranges::copy_fn) (std::vector<int>&, std::ostream_iterator<int>)'
required from here
These are basically the same errors that I see in VC++ for my snippet.
Here is a link: https://godbolt.org/z/pEfBb4
I would expect these two would work interchangeably. Why is it no so?

Just to clarify for others looking at the question:
The unit test work because its ranges::ostream_iterator and not std::ostream_iterator that is used in that snippet.
The std::ostream_iterator does not work because it doesn't satisfy the range Iterator concept since it's not default constructible.

Related

How to initialize a vector in c++ in visual studio code [duplicate]

This question already has answers here:
Visual Studio Code c++11 extension warning
(9 answers)
Visual Studio Code: code not running for C++11
(1 answer)
Closed 10 months ago.
I just set up visual studio code and made a very basic c++ program to test it:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> vec = {1, 2, 3, 4, 5};
for (const auto &i : vec) {
cout << i << endl;
}
}
I'm not sure if I did anything wrong, but I get the following errors:
test.cpp:7:17: error: non-aggregate type 'vector<int>' cannot be initialized with an initializer list
vector<int> vec = {1, 2, 3, 4, 5};
^ ~~~~~~~~~~~~~~~
test.cpp:8:16: warning: 'auto' type specifier is a C++11 extension [-Wc++11-extensions]
for (const auto &i : vec) {
^
test.cpp:8:24: warning: range-based for loop is a C++11 extension [-Wc++11-extensions]
for (const auto &i : vec) {
^
2 warnings and 1 error generated.
In cpp standard, it says its using c++20. I'm not sure what compiler I'm using, because in settings it looks like it is using clang, but when it runs, the description says:
cd "/Users/(my name)/Dropbox/Mac/vsCodeProjects/c:c++/" && g++ test.cpp -o test && "/Users/(my name)/Dropbox/Mac/vsCodeProjects/c:c++/"test
Because it says g++ there I'm not sure if it using clang after all, but I can't check the version of g++ because when I do it returns the clang version. I've tried everything I've seen and fiddled a lot with the tasks.json and the cpp standard json but nothing works. Any help is appreciated.

How can I use stl iterators with Eigen?

I am trying to use the Library Eigen in a project and I have to sort a vector. I tried to follow the documentation and it says that the library should work in the predictable way with the STL iterators and algorithms https://eigen.tuxfamily.org/dox-devel/group__TutorialSTL.html.
However when I try to run the following test code
#include <iostream>
#include <algorithm>
#include <eigen3/Eigen/Dense>
#include <eigen3/Eigen/Core>
int main()
{
Eigen::Array4i v = Eigen::Array4i::Random().abs();
std::cout << "Here is the initial vector v:\n" << v.transpose() << "\n";
std::sort(v.begin(), v.end());
std::cout << "Here is the sorted vector v:\n" << v.transpose() << "\n";
return 0;
}
I get the two following errors:
error: ‘Eigen::Array4i’ {aka ‘class Eigen::Array<int, 4, 1>’} has no member named ‘begin’
9 | std::sort(v.begin(), v.end());
| ^~~~~
error: ‘Eigen::Array4i’ {aka ‘class Eigen::Array<int, 4, 1>’} has no member named ‘end’
9 | std::sort(v.begin(), v.end());
I tested it with gcc 9.1.0 and 7.4.0 and my version of Eigen is 3.3.4. I am using Ubuntu 18.04 and the library is in the usual location /usr/include. All the other functionality I tried seem to work properly.
Is it a well known bug, is it a compiler problem or is it a version problem?
If you don't want to wait for the release of Eigen 3.4, you can use this:
std::sort(v.data(), v.data() + v.size());
The .data() method can replace the missing .begin(), but the .end() method must be constructed manually.

Unexpected error on declaring vector in c++

I'm getting an unexpectred error when I initialize a vector in the main.
I was expecting the following output:
0 1 2
I can't see why it's not working. I also writed the same code in another pc using the same compiler, and it works.
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> vett = {0,1,2};
for (int i : vett) {
cout << i << " ";
}
return 0;
}
error: could not convert '{0, 1, 2}' from '<brace-enclosed initializer list>' to 'std::vector<int>'|
You need to compile with at least C++11. List initialization came with C++11.
-std=c++11
You are compiling with something older than C++11, it does not support initializer list constructor.
If you are using Code::Blocks follow these steps:
Settings -> compiler -> compiler flags -> select C++11 or above

Why do I get a compilation error when using the emplace method for unordered_map?

#include <string>
#include <unordered_map>
using namespace std;
....
....
unordered_map<char, int> hashtable;
string str = "hello";
char lower = tolower(str[0]);
hashtable.emplace(lower, 1);
....
returns the following compilation errors:
1 error C2780: 'std::pair<_Ty1,_Ty2> std::_Hash<_Traits>::emplace(_Valty &&)' : expects 1 arguments - 2 provided
2 IntelliSense: no instance of function template "std::tr1::unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>::emplace [with _Kty=char, _Ty=int, _Hasher=std::hash<char>, _Keyeq=std::equal_to<char>, _Alloc=std::allocator<std::pair<const char, int>>]" matches the argument list
You are using an old version of Visual C++ which did not correctly support emplace. Probably Visual C++ 2010.
As the Visual C++ Team Blog once said:
As required by C++11, we've implemented
emplace()/emplace_front()/emplace_back()/emplace_hint()/emplace_after()
in all containers for "arbitrary" numbers of arguments (see below).
(...)
VC10 supported emplacement from 1 argument, which was not
especially useful.
The best solution would be to upgrade to the latest version of the compiler.
Following some extensions which could fix your issue
#include <utility> // for std::pair
std::unordered_map<char, int> hashtable;
char lower = 'A';
hashtable.emplace(std::pair<char, int>(lower, 1));
If your pasted code compiles seems to be depending on the underlying compiler. Handling to emplace a std::pair works for e.g. c++11--according to the spec (e.g. cplusplus.com) your code snippet should work with c++14.

Use of custom subscript operator with Boost.Lambda

I'm using Visual Studio 2005 and Boost 1.37. I also tested this same code on Visual Studio 2012 Express Desktop and Boost 1.50 without success.
I want to use a Boost.Lambda by accessing a custom subscript operator on my type. It also happens when using with std::array, so I'll illustrate the problem with the std::array type:
#include <vector>
#include <array>
#include <algorithm>
int main() {
std::vector<std::array<int, 3>> arrays;
arrays.push_back(make_array(1, 2, 3));
arrays.push_back(make_array(5, 5, 6));
std::for_each(arrays.begin(), arrays.end(), (_1[0])); //This line fails!
return 0;
}
The errors are:
error C2664: 'boost::lambda::detail::unspecified::unspecified(const boost::lambda::detail::unspecified &)' : cannot convert parameter 1 from 'int' to 'const boost::lambda::detail::unspecified &'
Reason: cannot convert from 'int' to 'const boost::lambda::detail::unspecified'
No constructor could take the source type, or constructor overload resolution was ambiguous
... ad infinitum...
I found this page: Extending return type deduction system
But I couldn't successfully implement it.
Does anyone know what can be done here?