Cannot use .begin() or .end() on an array
Arrays have no member functions as they aren't a class type. This is what the error is saying.
You can use std::begin(arr)
and std::end(arr)
from the <iterator>
header instead. This also works with types that do have .begin()
and .end()
members, via overloading:
#include <array>
#include <vector>
#include <iterator>
int main()
{
int c_array[5] = {};
std::array<int, 5> cpp_array = {};
std::vector<int> cpp_dynarray(5);
auto c_array_begin = std::begin(c_array); // = c_array + 0
auto c_array_end = std::end(c_array); // = c_array + 5
auto cpp_array_begin = std::begin(cpp_array); // = cpp_array.begin()
auto cpp_array_end = std::end(cpp_array); // = cpp_array.end()
auto cpp_dynarray_begin = std::begin(cpp_dynarray); // = cpp_dynarray.begin()
auto cpp_dynarray_end = std::end(cpp_dynarray); // = cpp_dynarray.end()
}
Can std::begin work with array parameters and if so, how?
Yes, std::begin
and std::end
can work with parameters that are C style arrays.
The trick is in passing a parameter that's a C style array. When you specify a 1D array as a normal parameter to a normal function, its type is silently adjusted from "array of T" to "pointer to T". When you call that function, what gets passed isn't the array (as an array), but a pointer to the first element of the array.
It is, however, possible to pass an array by reference to a function template:
template <class T, size_t N>
void function(T (&array)[N]) {
// function body here
}
In this case, where you're passing an actual array (albeit, by reference) rather than a pointer, you can use std::begin
and std::end
perfectly well. For example:
template <class T, size_t N>
T sum(T (&array)[N]) {
return std::accumulate(std::begin(array), std::end(array), T());
}
Now passing an array is trivial, such as:
int array[] = {1, 2, 3, 4};
auto total = sum(array);
std::begin
and std::end
themselves are (or at least can be) implemented similarly to sum
--the array is passed by reference, so they can look something like this:
template <class T, size_t N>
T *begin(T (&array)[N]) {
return array;
}
template <class T, size_t N>
T *end(T (&array)[N]) {
return array + N;
}
Note that although these were added to the standard more recently, they don't require any particularly tricky use of templates, so the implementation above should work fine with a plain old C++98 compiler (and, if memory serves, even with pre-standard compilers such as VC++ 6).
begin and end function for built-in array types
The problem that the compiler faces, is that it has no way to guess the size of argv, because it is not an array but a mere pointer.
Arrays can always be used as pointers, because an array can decay to a pointer to its first element. But the inverse is false! You can access the elements of an array through the array or through a pointer exactly the same, but the pointer and the array are not the same:
int a[5];
int *p = a; // p[i] and a[i] are now the same
size_t s = sizeof(a); // s is 5 * sizeof(int) 20 on common (32 bits) architectures
size_t s2 = sizeof(p); // s2 is just sizeof(int *) 4 on 32 bits architecture
The convention says that argv has argc elements (and that argv[argc] is a null pointer). But std::begin
and std::end
do not make use of that convention. So do it by hand as a nice programmer:
#include <iostream>
#include <iterator>
int main(int argc,char *argv[])
{
char **first=argv,**last=argv + argc;
}
std::begin and std::end not working with pointers and reference why?
Given just a pointer to the start of an array, there's no way to determine the size of the array; so begin
and end
can't work on pointers to dynamic arrays.
Use std::vector
if you want a dynamic array that knows its size. As a bonus, that will also fix your memory leak.
The third case fails because, again, you're using (a reference to) a pointer. You can use a reference to the array itself:
int (&refOfFirst)[3] = first;
or, to avoid having to specify the array size:
auto & refOfFirst = first;
and begin
and end
will work on this exactly as they would work on first
itself.
Use std::begin(), std::end() to convert ArrayXd to stl vector,
std::begin(vec.data())
cannot work because data() returns a raw pointer which cannot convey the number of elements in the vector. This version is the best one of yours:
std::vector<double> my_vec(e_array.data(), e_array.data() + 5);
And slightly better:
std::vector<double> my_vec(e_array.data(), e_array.data() + e_array.size());
And you may also be able to do this with many containers, but not with Eigen's ArrayXd in particular, because it lacks begin()
and end()
(related: http://eigen.tuxfamily.org/bz/show_bug.cgi?id=231).
std::vector<double> my_vec(foo.begin(), foo.end());
Related Topics
Getting the Current Time (In Milliseconds) from the System Clock in Windows
What's the Point of Std::Unique_Ptr::Get
How to Build Openssl with Mingw in Windows
Qthread Emits Finished() Signal But Isrunning() Returns True and Isfinished() Returns False
Integrate Type Name in Static_Assert Output
Why Does the "Static" Keyword Have So Many Meanings in C and C++
Two Dimensional Array Using Vector
Member Initializer Does Not Name a Non-Static Data Member or Base Class
How to Set Application Icon in a Qt-Based Project
Assigning a String of Characters to a Char Array
Opencv - Dll Missing, But It's Not
Is It Ever Not Safe to Throw an Exception in a Constructor
C++ Inheritance via Dominance Warning