C++ array wrapper - c++

I've wanted a wrapper around arrays, such, it would be stored at the stack - to be not concerned about memory releasing - be initializable via brace lists, and possibly be substitutable in any place of an ordinary array. Then, I've produced the following code. And now am wondering, have I missed something. -- So - is it what I've wanted?
template<class T, size_t size>
struct Array
{
T body[size];
operator T* () { return body; }
};
Edit:
I might be imprecise. The wrapper is only for constructional purpose. It shall be used for constructing arrays from brace lists, when being in an initialization list (primarily). Like
class A {
protected: A(int array[])
...
class B : public A {
public: B() :
A( (Array<int, 2>) {{ 1, 2 }} )
...
There was a proposition of a const version of the casting operator. - I've been considering this, but am not sure, is it really needed. While casting to const T[] is done implicitly through the existing operator, and a constant array can be defined by giving T = const ..., is there still a reason?

For a basic example, I don't think there's much you can improve on, except for a few helper functions. In particular, it would be nice to have a method that returns the size:
constexpr std::size_t size() const { return size; }
In addition, here are a few others:
const/non-const overloads of operator[N]:
As #ChristianRau stated in the comments, a operator T* provides a non-const version. We can implement the const version as such:
T const& operator [](std::size_t n) const
{
return body[n];
}
// similarly for non-const:
T& operator [](std::size_t n) { return body[n]; }
begin() and end() sequencers (very useful e.g. for the C++11 range-based for):
T* begin() { return body; }
T* end() { return body + size; }
// const versions... very much the same
T const* cbegin() const { return body; }
T const* cend() const { return body + size; }
T const* begin() const { return cbegin(); }
T const* end() const { return cend(); }
an at() method, which includes bounds checking (as opposed to operator[] by convention):
T const& at(std::size_t offset) const
{
// You should do bounds checking here
return body[offset];
}
// also a non-const version again..
It would also be nice to have a constructor that takes an std::initializer_list<T> so that you don't have to use the aggregate-initialization:
#include <algorithm>
#include <initializer_list>
template <typename T, std::size_t N>
struct Array
{
...
Array(std::initializer_list<T> const& list)
{
std::copy(list.begin(), list.end(), body);
}
...
};
Here is another one suggested by #DyP (initializer list always copies, perfect forwarding tries to avoid that):
template <typename T, std::size_t N>
struct Array
{
...
template <typename... Args>
// possibly constexpr
Array(Args&&... args) : body{ std::forward<Args>(args)... }
{}
...
};
Here is the program in action if you want to see it -- http://ideone.com/Zs27it#view_edit_box
There are others features you can include, but as I said this is a basic example, and you would most likely be better off using something like std::array which has more or less the same methods.

Related

How to iterate (outside a class) a private member which is a vector<unique_ptr<T>>

class Organization {
private:
vector<unique_ptr<Employee>> employees_;
vector<unique_ptr<Item>> items_;
}org;
I need to have a facility outside the class to iterate over the employees and items and call their members, like the following...
for(auto const& e : getEmployees()) { e.get()->getName(); }
But I cannot make getEmployees() function to return employees_, as vector of unique_ptrs is not copyable
So currently I'm having a for_each_employee function
template<class callable>
void Organization::for_each_employee(callable f) {
for(auto const& e : employees_) {
f(e.get());
}
}
// And I use it like,
org.for_each_employee([](Employee* e){ e->getName(); });
But I do not like this idea as I'll have to write for_each_employee and for_each_item. I have similar other classes of the similar structure. So I will end up writing lot of for_each_XX type functions. This is not what I want.
Can I have generic for_each function that are friends of these classes (like Organization that contain vector of unique_ptrs)?
How to iterate (outside a class) a private member which is a vector<unique_ptr<T>>
The simplest and quite readable approach is to provide an access method that returns a possibly const-qualified reference to the data member. This way, you don't try to copy non-copyable members.
const vector<unique_ptr<Item>>& getItems()
{
return items_;
}
which can be used like this
for (const auto& item : organizationInstance.getItems())
item->doStuff();
You can return reference of employee_ in getEmployees() to iterate
const vector<unique_ptr<Employee>>& getEmployees()
{
return employee_;
}
What you're looking for is iterators. std::vector::begin() and std::vector::end() return iterators to the first and to the one-past-the-end elements of the vector. Then you can do stuff like.
for (auto iter = organization.get_employees_begin(); iter != organization.get_employees.end(); ++iter) {
do_something(*iter);
}
Where
class Organization {
auto get_employees_begin() { return employees_.begin(); }
auto get_employees_begin() const { return employees_.begin(); }
auto get_employees_end() { return employees_.end(); }
auto get_employees_end() const { return employees_.end(); }
}
The const versions return const iterators, which are similar to pointers-to-const in that they don't allow modification of the vector. The added benefit of this method over returning a reference to the vector is that it completely decouples the implementation from the interface. If you don't care about that for whatever reason, you can use this instead.
class Organization {
auto& get_employees() { return employees_; }
const auto& get_employees() const { return employees_; }
}
This will allow you to use all vector utilities but it will also make all your code that relies on them break if the internal container changes from a vector to something else.
In any case, you might not want to provide the non-const functions if the vector should not be modified directly.
To allow only iterating, not giving any more vector-specific operations You can use boost::range
auto getItems() {
return boost::make_iterator_range(employees_.begin(), employees_.end());
}
Here is a simple span class. It is similar to gsl::span. It represents a view into a contiguous buffer of T elements (like in an array):
template<class T>
struct span {
T* begin() const { return b; }
T* end() const { return e; }
T* data() const { return begin(); }
std::size_t size() const { return end()-begin(); }
bool empty() const { return size()==0; }
span( T* s, T* f ):b(s),e(f) {}
span( T* s, std::size_t length ):span(s, s+length){}
span() = default;
template<class A>
span( std::vector<T, A>& v ):
span(v.data(), v.length() )
{}
template<class A>
span( std::vector<std::remove_const_t<T>, A> const& v ):
span(v.data(), v.length() )
{}
template<std::size_t N>
span( T(& arr)[N] ):
span(arr, N)
{}
template<std::size_t N>
span( std::array<T, N>& arr ):
span(arr.data(), N)
{}
template<std::size_t N>
span( std::array<std::remove_const_t<T>, N> const& arr ):
span(arr.data(), N)
{}
private:
T* b = 0;
T* e = 0;
};
simply have your getEmployees return a span<std::unique_ptr<Employee> const>.
This exposes everything the caller needs to iterate over it efficiently, and no more.
The simpler alternative is to return a std::vector<std::unique_ptr<Employee>> const&, but that leaks implementation details that are utterly irrelevant to the consumer of getEmployee.

How to let a `std::vector<int32_t>` take memory from a `std::vector<uint32_t>&&`?

template<typename T>
struct raster {
std::vector<T> v;
template<typename U, typename = std::enable_if_t<sizeof(T) == sizeof(U)>>
raster(raster<U>&& other){
// What code goes here?
}
}
Suppose we have raster<uint32_t> r such that r.v.size() is in the millions, and a guarantee that all its elements are within int32_t's range. Is it possible for raster<int32_t>::raster(raster<uint32_t>&& other) to avoid copying the memory backing other.v?
Or should I just do something like *reinterpret_cast<raster<int32_t>*>(&r) instead of calling that constructor?
There is no legal way to do this in C++; you can only move buffers from a std::vector to another std::vector of the exact same type.
There are a variety of ways you can hack this. The most illegal and evil would be
std::vector<uint32_t> evil_steal_memory( std::vector<int32_t>&& in ) {
return reinterpret_cast< std::vector<uint32_t>&& >(in);
}
or something similar.
A less evil way would be to forget it is a std::vector at all.
template<class T>
struct buffer {
template<class A>
buffer( std::vector<T,A> vec ):
m_begin( vec.data() ),
m_end( m_begin + vec.size() )
{
m_state = std::unique_ptr<void, void(*)(void*)>(
new std::vector<T,A>( std::move(vec) ),
[](void* ptr){
delete static_cast<std::vector<T,A>*>(ptr);
}
);
}
buffer(buffer&&)=default;
buffer& operator=(buffer&&)=default;
~buffer() = default;
T* begin() const { return m_begin; }
T* end() const { return m_end; }
std::size_t size() const { return begin()==end(); }
bool empty() const { return size()==0; }
T* data() const { return m_begin; }
T& operator[](std::size_t i) const {
return data()[i];
}
explicit operator bool() const { return (bool)m_state; }
template<class U>
using is_buffer_compatible = std::integral_constant<bool,
sizeof(U)==sizeof(T)
&& alignof(U)==alignof(T)
&& !std::is_pointer<T>{}
>;
template<class U,
std::enable_if_t< is_buffer_compatible<U>{}, bool > = true
>
buffer reinterpret( buffer<U> o ) {
return {std::move(o.m_state), reinterpret_cast<T*>(o.m_begin()),reinterpret_cast<T*>(o.m_end())};
}
private:
buffer(std::unique_ptr<void, void(*)(void*)> state, T* b, T* e):
m_state(std::move(state)),
m_begin(begin),
m_end(end)
{}
std::unique_ptr<void, void(*)(void*)> m_state;
T* m_begin = 0;
T* m_end = 0;
};
live example: this type erases a buffer of T.
template<class T>
struct raster {
buffer<T> v;
template<typename U, typename = std::enable_if_t<sizeof(T) == sizeof(U)>>
raster(raster<U>&& other):
v( buffer<T>::reinterpret( std::move(other).v ) )
{}
};
note that my buffer has a memory allocation in it; compared to millions of elements that is cheap. It is also move-only.
The memory allocation can be eliminated through careful use of the small buffer optimization.
I'd leave it move-only (who wants to accidentally copy a million elements?) and maybe write
buffer clone() const;
which creates a new buffer with the same contents.
Note that instead of a const buffer<int> you should use a buffer<const int> under the above design. You can change that by duplicating the begin() const methods to have const and non-const versions.
This solution relies on your belief that reinterpreting a buffer of int32_ts as a buffer of uint32_ts (or vice versa) doesn't mess with anything. Your compiler may provide this guarantee, but the C++ standard does not.
The problem is that the implementation of the vector template itself may be specialised for the type. For some weird whacky reason we don't understand today, the top-level vector might need an extra member not provided in vector, so simply reinterpret casting will not work safely.
Another evil approach might be to look at the Allocator of your two vectors.
If this was
a custom allocator you had written and both were a derived class from vector
and you wrote an overload in the class for swap and =&&
within which you created wrapped tmp vectors to swap with
and detected that the Allocator was being called within those temporary objects constructors/destructors, and on the same thread
to release and reallocate the same sized array
Then, perhaps you could legitimately pass the memory buffer between them without resetting the content.
But that is a lot of fragile work!

Template of array of function pointers

I've got a few functions, some of which are overloaded and some are templates, ex.:
void fun1 (vector<string> &a, int b);
void fun1 (vector<double> &a, int b);
template <typename t>
void fun2 (t a[], int b);
and so on. Every function I use has a version for 2 data types, one is an array and the other one is a vector (a vector of strings, a vector of doubles, an array of strings and an array of doubles). The question is, can I create a template for an array of pointers? Is there any way of doing it, apart from:
void (*strvecfun[])(vector <string>&, long, long)={fun1, fun2};
void (*dblvecfun[])(vector <double>&, long, long)={fun1, fun2};
void (*strarrfun[])(string [], long, long)={fun1, fun2};
and so on?
You can use
template<typename Func>
struct func_array {
static Func *const data[];
};
template<typename Func>
Func *const func_array<Func>::data[] = { fun1, fun2 };
And later call
func_array<void(std::vector<double>&, long, long)>::data[0](dvec, l1, l2);
func_array<void(std::vector<string>&, long, long)>::data[1](svec, l1, l2);
// ...and so forth
This requires that there are matching overloads for all the signatures you're going to use of all functions you put into the list, naturally.
Instead of having 2 implementations, have one. Have your data take an array_view<double>:
template<class T>
struct array_view {
// can make this private:
T* b = 0; T* e = 0;
// core methods:
T* begin() const { return b; }
T* end() const { return e; }
// utility methods:
size_t size() const { return end()-begin(); }
T& front() const { return *begin(); }
T& back() const { return *std::prev(end()); }
bool empty() const { return begin()==end(); }
// core ctors:
array_view(T* s, T* f):b(s),e(f) {};
array_view()=default;
array_view(array_view const&)=default;
// derived ctors:
array-view(T* s, size_t l):array_view(s, s+l) {};
template<size_t N>
array_view( T(&arr)[N] ):array_view(arr, N) {};
template<size_t N>
array_view( std::array<T,N>&arr ):array_view(arr.data(), N) {};
template<class A>
array_view( std::vector<T,A>& v ):array_view(v.data(), v.size()) {};
// extra ctors that fail to compile if `T` is not const, but
// are mostly harmless even if `T` is not const, and useful if
// `T` is const. We could do fancy work to disable them, but
// I am lazy:
using non_const_T = std::remove_const_t<T>;
template<class A>
array_view( std::vector<non_const_T,A>const& v ):array_view(v.data(), v.size()) {};
template<size_t N>
array_view( std::array<non_const_T,N>const&arr ):array_view(arr.data(), N) {};
array_view( std::initializer_list<non_const_T> il ):array_view(il.data(), il.size()) {};
};
array_view acts like a view into a container, and can be implicitly converted from a number of std containers as well as raw arrays.
void fun1 (array_view<std::string> a);
a.size() tells you how long it is, and it can be iterated over in a for(:) loop even.
std::vector<T>& is far more powerful than what you need. By using array_view, we only expose what you need (access to elements), and thus are able to take both an array and a container.
If you pass in a "real" C style array, it will auto-deduce the length. If you instead pass in a pointer (or a [] really-a-pointer array), you also have to pass the length like:
fun1( {ptr, length} );
Create a function called max that will return the value of the largest element in an array.
The arguments to the function should be the address of the array size.
Make this function into a template so it will work with an array of any numerical types.

using range-for loop: too few arguments to function call, single argument 'a' was not specified

I'm a beginner in C++ and I'm reading section 3.4.1 Parameterized Types of the C++ programming language 4th ed by Bjarne Stroustrup.
What this chapter tries to show is defining the begin() and end() function in the user-defined type Vector so that a range-for loop(i.e. for (auto& s: vs )) is supported .
After defining the begin() and end() functions. I'm getting the error too few arguments to function call, single argument 'a' was not specified when I put them into use.
Version 1
The text really had this:
In user.cpp:
void f2(const Vector<string> & vs)
{
for (auto& s: vs) //member function 'begin' not viable: 'this' argument has type 'const Vecto<Std::__1::basic_string<char> >
cout << s << '\n';
}
Xcode then tells me that member function 'begin' not viable: 'this' argument has type 'const Vecto<Std::__1::basic_string<char> >', but function is not marked const.
So I went ahead and marked the functions const.
In Vector.h:
template<typename T>
class Vector{
public:
const T* begin(Vector<T>& a);
const T* end(Vector<T>& b);
};
In Vector.cpp:
#include "Vector.h" //get the interface
//To support the range-for loop for our Vector, we must define suitable begin() and end() functions:
template <typename T>
const T* Vector<T>::begin(Vector<T>& x)
{
return & x[0];
}
template <typename T>
const T* Vector<T>::end(Vector<T>& x)
{
return x.begin()+x.size(); //pointer to one past last element.
}
The error persists.
Version 2
The next thing that i did was remove const from function f2(). I get this new error too few arguments to function call, single argument 'a' was not specified. Removing const from the functions in Vector.h and Vector.cpp didn't make any difference.
In user.cpp:
#include "Vector.h"
void f2(Vector<string> & vs)
{
for (auto& s: vs) //too few arguments to function call, single argument 'a' was not specified
cout << s << '\n';
}
In Vector.h:
template<typename T>
class Vector{
public:
const T* begin(Vector<T>& a);
const T* end(Vector<T>& b);
};
In Vector.cpp:
#include "Vector.h" //get the interface
//To support the range-for loop for our Vector, we must define suitable begin() and end() functions:
template <typename T>
const T* Vector<T>::begin(Vector<T>& x)
{
return & x[0];
}
template <typename T>
const T* Vector<T>::end(Vector<T>& x)
{
return x.begin()+x.size(); //pointer to one past last element.
}
I have included parts of the code that I think are most critical, otherwise, full codes are available here.
So I went ahead and marked the functions const.
You didn't mark your member functions const. Besides that, they should be parameterless. For that, you need
const T* begin() const;
^^^^^
Note that you need to make the implementation available in the header file, not in a separate .cpp file (unless you include that at the bottom of the header, and make sure there is no attempt to compile it.) It also makes sense to provide non-const overloads.
template<typename T>
class Vector{
public:
const T* begin() const {return &x[0]; }
const T* end() const { return &c[0] + size(); }
T* begin() {return &x[0]; }
T* end() { return &c[0] + size(); }
size_t size() const { /* return the size */ }
};
You have two different problems. The first one with the constness is because your begin and end functions are not marked as const which makes them not callable on a constant object. Change declaration and definition to
const T* begin(Vector<T>& a) const;
const T* end(Vector<T>& b) const;
Note the const keyword after the function. Also note that you can have both constant and non-constant functions with the same name.
The other problem, which you have in both versions, is that you expect the functions to take an argument. They don't. Instead they operate on this. So change to this:
template <typename T>
const T* Vector<T>::begin() const
{
return &yourInternalVectorVariable[0];
}
Do the same for the end function.

Constructing an object that can be iterated using a range based for

I wrote a short utility function an object to "wrap" an iterable container, so that I could walk it backwards using a range based for.
template <typename Iterable>
struct ReverseWrapper {
private:
Iterable& m_iterable;
public:
ReverseWrapper(Iterable& iterable) : m_iterable(iterable) {}
auto begin() const ->decltype(m_iterable.rbegin()) {
return m_iterable.rbegin();
}
auto end() const ->decltype(m_iterable.rend()) {
return m_iterable.rend();
}
};
template <typename Iterable>
ReverseWrapper<Iterable> reverseIterate(Iterable& list) {
return ReverseWrapper<Iterable>(list);
}
This works for C++ iterable objects, but not for static arrays. What is required for an object to support iteration using a range based for? What would be the best way to approach this problem?
The actual rule to choose begin and end functions for iterables is the following: use the class begin and end function if it has some. Use overloads of the global functions std::begin and std::end if some are provided.
Static arrays not being class/struct, they don't/can't have member functions. The functions called by the foreach loop are the global functions std::begin and std::end, taking an array as parameter. Assuming std::rbegin and std::rend existed, you would have to construct your wrapper the following way:
template <typename Iterable>
struct ReverseWrapper {
private:
Iterable& m_iterable;
public:
ReverseWrapper(Iterable&& iterable) : m_iterable(iterable) {}
auto begin() const -> decltype(rbegin(m_iterable)) {
return rbegin(m_iterable);
}
auto end() const -> decltype(rend(m_iterable)) {
return rend(m_iterable);
}
};
template<typename Iterable>
auto reverseIterate(Iterable&& list)
-> ReverseWrapper<Iterable>
{
return ReverseWrapper<Iterable>(std::forward<Iterable>(list));
}
Even though std::rbegin and std::rend exist in the c++14 standard, they are not available in the c++11 one. So, to get the above code to work with c++11, you would have to implement these functions by hand:
template<typename T, std::size_t N>
auto rbegin(T (&array)[N])
-> std::reverse_iterator<T*>
{
return std::reverse_iterator<T*>(std::end(array));
}
template<typename T, std::size_t N>
auto rend(T (&array)[N])
-> std::reverse_iterator<T*>
{
return std::reverse_iterator<T*>(std::begin(array));
}
In your code, the Iterable template parameter needs to have begin and end member functions. Normal C++ arrays do not have those functions. Instead you have to use std::begin and std::end, which are part of the C++11 standard.
However, there doesn't seem to be any std::rbegin or std::rend functions, which means you have to implement those yourself, possibly also implement the actual iterator class.