Can you cast a pointer, into an array? - c++

I have a pointer "a", it is of type A*. I now that there is n objects of type A at that address and I want to iterate over them.
I would like to cast it to A[n], so that I can use the c++11 range-for and write for (auto temp : a){...}.
Of course, I can use a classic for(int i=0; i<n; i++) {temp=a[i]; ...} but the range-for is cleaner.

In reasonable code, I'd shy away from it. But C++ allows you to commit acts of sheer devilry. In that vein, I offer a solution:
At the expense of some considerable obfuscation, you can write some preparatory templates:
namespace std
{
template <typename T> T* begin(std::pair<T*, T*> const& a)
{
return a.first;
}
template <typename T> T* end(std::pair<T*, T*> const& a)
{
return a.second;
}
}
Then you can write something like
for (auto&& i : std::make_pair(a, a + n)){
}
The template stuff brings in suitable definitions of begin and end which is required by the range for loop.

Related

Moving in range-based loop in generic C++ code?

Imagine that you have this generic pseudo-code:
template<typename Iterable>
void f(Iterable&& iterable)
{
...
}
We want to handle rvalue and lvalue references to iterable objects1, and the idea is that the function handles the container performing operations element by element.
It is plausible that we want to forward the reference specification of the container to the elements. In other words, if iterable is an rvalue reference, the function will have to move the elements from the container.
Using C++17, I would do
auto [begin, end] = [&] {
if constexpr(std::is_lvalue_reference_v<Iterable>)
return std::array{std::begin(iterable),
std::end(iterable)};
else
return std::array{
std::make_move_iterator(std::begin(iterable)),
std::make_move_iterator(std::end(iterable))};
}();
std::for_each(begin, end, [&](auto&& element)
{
...
});
Obviously, this is not the best code to maintain2, error prone and probably not so easy to optimize for the compiler.
My question is: it could be possible, for future C++ standards, to introduce the concept of forwarding range-based loops? It would be nice if this
for(auto&& el : std::move(iterable))
{
...
}
could handle el as rvalue reference. In this way, this would be possible:
template<typename Iterable>
void f(Iterable&& iterable)
{
for(auto&& el : std::forward<Iterable>(iterable))
{
/*
* el is forwarded as lvalue reference if Iterable is lvalue reference,
* as rvalue reference if Iterable is rvalue reference
*/
external_fun(std::forward<decltype(el)>(el));
}
}
I am concerned about code-breaking changes, but at the same time I am not able to think about situations in which passing a rvalue reference as argument of a range based loop is expected to work without moving objects.
As suggested, I tried to write down how I would change the 6.5.4 section of the standard. The draft can be read at this address.
Do you think that it would be possible to introduce this feature without introducing serious issues?
1Checked with C++20 concepts or static_asserts
2And it's quite worse without C++17
This won't work. Fundamentally there are two kinds of things you can iterate over: those that own the elements, and those that don't. For non-owning ranges, the value category of the range is immaterial. They don't own their elements and so you can't safely move from them. The range-based for loop must work with both kind of ranges.
There are also corner cases to consider (e.g., proxy iterators). The range-based for loop is basically syntax sugar that imposes only a very minimal set of requirements on the thing being iterated over. The benefit is that it can iterate over lots of things. The cost is that it doesn't have much room to be clever.
If you know that the iterable in fact owns its elements (so that moving is safe), then all you need is a function that forwards something according to the value category of some other thing:
namespace detail {
template<class T, class U>
using forwarded_type = std::conditional_t<std::is_lvalue_reference<T>::value,
std::remove_reference_t<U>&,
std::remove_reference_t<U>&&>;
}
template<class T, class U>
detail::forwarded_type<T,U> forward_like(U&& u) {
return std::forward<detail::forwarded_type<T,U>>(std::forward<U>(u));
}
You may add a wrapper, something like:
template <typename T> struct ForwardIterable;
template <typename T> struct ForwardIterable<T&&>
{
ForwardIterable(T&& t) : t(t) {}
auto begin() && { return std::make_move_iterator(std::begin(t)); }
auto end() && { return std::make_move_iterator(std::end(t)); }
T& t;
};
template <typename T> struct ForwardIterable<T&>
{
ForwardIterable(T& t) : t(t) {}
auto begin() { return std::begin(t); }
auto end() { return std::end(t); }
auto begin() const { return std::begin(t); }
auto end() const { return std::end(t); }
T& t;
};
template <typename T>
ForwardIterable<T&&> makeForwardIterable(T&& t)
{
return {std::forward<T>(t)};
}
And then
for(auto&& el : makeForwardIterable(std::forward(iterable)))
{
// ...
}
your suggestion will introduce breaking changes. Assume this piece of code:
vector<unique_ptr<int>> vec;
for (int i = 0; i < 10; ++i)
vec.push_back(make_unique<int>(rand()%10));
for (int i = 0; i < 2; ++i) {
for (auto &&ptr : move(vec))
cout << (ptr ? *ptr : 0) << " ";
cout << endl;
}
With current standard, it'll print two same lines
Write a simple range type. It stores two iterators and exposes begin() and end().
Write a move_range_from(Container&&) function that returns a range of move iterators.
Write move_range_from_if<bool>(Container&&) that creates a range or moves from the range conditionally.
Support lifetime extension in both.
template<typename Iterable>
void f(Iterable&& iterable) {
auto move_from = std::is_rvalue_reference<Iterable&&>{};
for(auto&& e: move_range_from_if< move_from >(iterable) ) {
}
}
does what you want.
This supports both ranges (non-owning) and containers and doesn't require a language extension. And it doesn't break existing code.
The lifetime extension feature is so you can call these functions with prvalues; without it, for(:) loops don't lifetime extend arguments to the loop target function call.

Comparer that takes the wanted attribute

In order to use a standard function like std::sort on some standard container Container<T>
struct T{
int x,y;
};
based on the y value, you need to write something like (for example):
std::vector<T> v;
//fill v
std::sort(v.begin(),v.end(),[](const auto& l,const auto& r){
return l.y<r.y;
});
The comparer that was written as lambda function is used too much and re-written again and again during the code for various classes and attributes.
Considering the case where y's type is comparable (either like int or there is an overload for the < operator), is there any way to achieve something like:
std::sort(v.begin(),v.end(),imaginary::less(T::y)); // Imaginary code
Is it possible in C++ to write such a function like less? or anything similar?
I am asking because I remember something like that in some managed language (I am not sure maybe C# or Java). However, I am not sure even about this information if it is true or not.
template<typename T, typename MT>
struct memberwise_less
{
MT T::* const mptr;
auto operator()(const T& left, const T& right) const
{ return (left.*mptr) < (right.*mptr); }
};
template<typename T, typename MT>
memberwise_less<T, MT> member_less(MT T::*mptr)
{
return { mptr };
}
and then you can do
std::sort(v.begin(), v.end(), member_less(&T::y));

Generic for loop for elementary and complex type

Suppose I have those two std::vector:
std::vector<int> v_int(1000);
std::vector<T> v_T(1000); // Where T is copy-costy type
if I need to loop through them (sepereatly) without the need for editing the items I may use:
for(const auto item:v_int){
//...
}
for(const auto& item:v_T){ //Note &
//...
}
Iterating using const auto item:v_T is too bad since a copy will be performed in each iteration. However, using const auto& item:v_int is not optimal but not that bad. So if I need a code that deal with both them I used to use const auto& item:v.
Question: Is there a generic way to write the for loop that will use the best declaration for both of them? Something like:
template <typename T>
void iterate(const std::vector<T> v){
for(const auto/*&*/ item:v){ // activate & if T is not elementary type
//...
}
}
You can do this using the standard type traits:
template <typename T>
using select_type = std::conditional_t<std::is_fundamental<T>::value,
const T, const T&>;
template <typename T>
void iterate(const std::vector<T> v){
for(select_type<T> item:v){ // activate & if T is not elementary type
//...
}
}
However, I question the wisdom of doing this. It just clutters the code for something which is unlikely to make any difference.
Use auto&& when you just don't care. Use auto const& when you must guarantee it is not edited.
References are aliases, and in an immediate context like a loop are trivial to optimize out of existence, especially if the value is never modified.
There are some difficulties when a reference is passed over a compilation unit boundary to a function, which is why passing int by value instead of const& is advised sometimes, but that does not apply here.
I am not a specialist in template area but I think what bothers you is that in case of char the copy will copy only one byte while using & will copy sizeof(char*) bytes.
What comes to my mind is to use the sizeof(T).
In this case you can use
if (sizeof(T) >= sizeof(void*))
// use '&'
else
// don't use '&'
since sizeof is evaluated in the compilation time, this if branch will be optimized out by the compiler.
Personally I would just use const auto& for every case because the overhead is negligible unless you're needing to crunch some very large data sets in tight loops.
An approach to obtain what you want however might be to implement template specializations for your iterate method:
#include <iostream>
#include <string>
#include <vector>
template <typename T>
void iterate(const std::vector<T>& v){
for(const auto& item:v){
std::cout << item << std::endl;
}
}
template <>
void iterate(const std::vector<int>& v){
for(const auto item:v){
std::cout << "[" << item << "]" << std::endl;
}
}
int main()
{
std::vector<std::string> strings = { "foo", "bar" };
std::vector<int> numbers = { 1, 2 };
iterate(strings);
iterate(numbers);
}
Note: you're more likely to see a performance hit from copy constructing your vectors into the iterate function :)

Const converting std containers

Consider that I have a std::vector.
std::vector<int> blah;
blah.push_back(1);
blah.push_back(2);
I now want to pass the vector somewhere and disallow modifying the contents of the objects its contains while still allowing to modify the container when able:
// Acceptable use:
void call_something() {
std::vector<int> blah;
blah.push_back(1);
blah.push_back(2);
// Currently, compiler error because of mismatching types
something(blah);
}
void something(std::vector<const int>& blah)
{
// Auto translates to 'const int'
for ( auto& i : blah ) {
// User cannot modify i.
std::cout << i << std::endl;
}
blah.push_back(blah.size()); // This should be acceptable
blah.emplace_back(); // This should be acceptable
return;
}
// Unacceptable use:
void something_else(const std::vector<int>& blah)
{
// Because of const vector, auto translates to 'const int'
for ( auto& i : blah ) {
std::cout << i std::endl;
}
blah.push_back(blah.size()); // This will present an unacceptable compiler error.
blah.emplace_back(); // This will present an unacceptable compiler error.
return;
}
Is there an easy way to do this?
To enable the operations you wish to allow while preventing the others, you need to take a fine-grained approach to your function's interface. For example, if your calling code were to pass const iterators (begin and end) as well as a back inserter (or custom back emplacer functor), then exactly the subset of operations you showed would be possible.
template <class Iter, class F>
void something(Iter begin, Iter end, F&& append)
{
using value_type = typename std::iterator_traits<Iter>::value_type;
std::copy(begin, end, std::ostream_iterator<value_type>(std::cout, "\n"));
append(std::distance(begin, end));
append();
return;
}
That said I don't find your examples particularly compelling. Do you have a real scenario in which you must maintain mutable elements, pass a mutable container to a function, yet treat the passed elements as immutable?
There is no easy way to do this. One way would be to wrap a vector in a type that exposes only the functionality that you want to allow. For instance
template<typename T, typename A = std::allocator<T>>
struct vector_wrap
{
using iterator = typename std::vector<T, A>::const_iterator;
using const_iterator = typename std::vector<T, A>::const_iterator;
using size_type = typename std::vector<T, A>::size_type;
vector_wrap(std::vector<T, A>& vec)
: vec_(&vec)
{}
void push_back(T const& value) { vec_->push_back(value); }
void push_back(T&& value) { vec_->push_back(std::move(value)); }
size_type size() { return vec_->size(); }
iterator begin() const { return vec_->cbegin(); }
iterator end() const { return vec_->cend(); }
private:
std::vector<T, A> *vec_;
};
Since the above implementation only stores a pointer to the vector it wraps, you'll have to ensure that the lifetime of the vector is longer than that of vector_wrap.
You'll have to modify something and something_else so that they take a vector_wrap<int> as argument. Since vector_wrap::begin and vector_wrap::end return const_iterators, you'll not be allowed to modify existing elements within the for statement.
Live demo

Large POD as tuple for sorting

I have a POD with about 30 members of various types and I will be wanting to store thousands of the PODs in a container, and then sort that container by one of those members.
For example:
struct Person{
int idNumber;
....many other members
}
Thousands of Person objects which I want to sort by idNumber or by any other member I choose to sort by.
I've been researching this for a while today and it seems the most efficient, or at least, simplest, solution to this is not use struct at all, and rather use tuple for which I can pass an index number to a custom comparison functor for use in std::sort. (An example on this page shows one way to implement this type of sort easily, but does so on a single member of a struct which would make templating this not so easy since you must refer to the member by name, rather than by index which the tuple provides.)
My two-part question on this approach is 1) Is it acceptable for a tuple to be fairly large, with dozens of members? and 2) Is there an equally elegant solution for continuing to use struct instead of tuple for this?
You can make a comparator that stores a pointer to member internaly so it knows which member to take for comparison:
struct POD {
int i;
char c;
float f;
long l;
double d;
short s;
};
template<typename C, typename T>
struct Comp {
explicit Comp(T C::* p) : ptr(p) {}
bool operator()(const POD& p1, const POD& p2) const
{
return p1.*ptr < p2.*ptr;
}
private:
T C::* ptr;
};
// helper function to make a comparator easily
template<typename C, typename T>
Comp<C,T> make_comp( T C::* p)
{
return Comp<C,T>(p);
}
int main()
{
std::vector<POD> v;
std::sort(v.begin(), v.end(), make_comp(&POD::i));
std::sort(v.begin(), v.end(), make_comp(&POD::d));
// etc...
}
To further generalize this, make make_comp take a custom comparator, so you can have greater-than and other comparisons.
1) Is it acceptable for a tuple to be fairly large, with dozens of members?
Yes it is acceptable. However it won't be easy to maintain since all you'll have to work with is an index within the tuple, which is very akin to a magic number. The best you could get is reintroduce a name-to-index mapping using an enum which is hardly maintainable either.
2) Is there an equally elegant solution for continuing to use struct instead of tuple for this?
You can easily write a template function to access a specific struct member (to be fair, I didn't put much effort into it, it's more a proof of concept than anything else so that you get an idea how it can be done):
template<typename T, typename R, R T::* M>
R get_member(T& o) {
return o.*M;
}
struct Foo {
int i;
bool j;
float k;
};
int main() {
Foo f = { 3, true, 3.14 };
std::cout << get_member<Foo, float, &Foo::k>(f) << std::endl;
return 0;
}
From there, it's just as easy to write a generic comparator which you can use at your leisure (I'll leave it to you as an exercise). This way you can still refer to your members by name, yet you don't need to write a separate comparator for each member.
You could use a template to extract the sort key:
struct A
{
std::string name;
int a, b;
};
template<class Struct, typename T, T Struct::*Member>
struct compare_member
{
bool operator()(const Struct& lh, const Struct& rh)
{
return lh.*Member < rh.*Member;
}
};
int main()
{
std::vector<A> values;
std::sort(begin(values), end(values), compare_member<A, int, &A::a>());
}
Maybe you want to have a look at boost::multi_index_container which is a very powerful container if you want to index (sort) object by different keys.
Create a class which can use a pointer to a Person member data to use for comparison:
std::sort(container.begin(), container.end(), Compare(&Person::idNumber));
Where Compare is:
template<typename PointerToMemberData>
struct Compare {
Compare(PointerToMemberData pointerToMemberData) :
pointerToMemberData(pointerToMemberData) {
}
template<typename Type
bool operator()(Type lhs, Type rhs) {
return lhs.*pointerToMemberData < rhs.*pointerToMemberData
}
PointerToMemberData pointerToMemberData;
};