I want to initialize a container with pointers to objects. I currently have a loop like this:
for(int i=0;i < n;i++) {
container.push_back(new Object());
}
Which C++ operation (i.e. similar to std::transform) is the right to replace this loop and initialize a container with n newly created objects?
Use std::generate:
constexpr int n = 10;
std::vector<Object*> v1(n);
std::generate(v1.begin(), v1.end(), [](){ return new Object(); });
or std::generate_n:
std::vector<Object*> v2;
v2.reserve(n); // pre-allocate sufficient memory to prevent re-allocations
// (you should have done in original loop approach as well)
std::generate_n(std::back_inserter(v2), n, [] { return new Object(); });
You could use std::generate_n and std::back_inserter with lambda.
std::generate_n(std::back_inserter(container), n, [] { return new Object(); });
The goal is this syntax:
std::vector<Object*> v1 = generate([](auto&&){ return new Object; }, 10).make_container();
where we say we want to generate 10 elements with a specific lambda, then we create a container of the asked for type.
It requires some boilerplate. First, an input iterator that counts and calls a function:
template<class F>
struct generator_iterator {
F f;
std::size_t i = 0;
using self=generator_iterator;
friend bool operator==(self const& lhs, self const& rhs){ return lhs.i==rhs.i; }
friend bool operator!=(self const& lhs, self const& rhs){ return lhs.i!=rhs.i; }
using reference=std::result_of_t<F const&(std::size_t const&)>;
using value_type=std::decay_t<reference>;
using difference_type=std::ptrdiff_t;
using pointer=value_type*;
using iterator_category=std::input_iterator_tag;
self& operator++(){++i; return *this;}
self operator++(int){auto tmp=*this; ++*this; return tmp;}
reference operator*()const{ return f(i); }
pointer operator->()const { return std::addressof(f(i)); }
friend difference_type operator-( self const& lhs, self const& rhs ) { return lhs.i-rhs.i; }
self& operator-=( difference_type rhs )& {
i-=rhs;
return *this;
}
self& operator+=( difference_type rhs )& {
i+=rhs;
return *this;
}
friend difference_type operator+( self lhs, difference_type rhs ) {
lhs += rhs;
return lhs;
}
friend difference_type operator-( self lhs, difference_type rhs ) {
lhs -= rhs;
return lhs;
}
};
Next, a range primitive, with a .make_container() method that lets you convert ranges to containers either by passing the type explicitly or implicitly:
template<class It>
struct range_t {
It b, e;
It begin() const { return b; }
It end() const { return e; }
private:
struct container_maker {
range_t const* self;
template<class C>
operator C()&& {
return {self->begin(), self->end()};
}
};
public:
container_maker make_container()const{
return {this};
}
// C is optional
template<class C>
C make_container()const{
return make_container();
}
};
template<class It>
range_t<It> range( It s, It f ) {
return {std::move(s), std::move(f)};
}
We then glue these together:
template<class F>
auto generate( F&& f, std::size_t count ) {
generator_iterator<std::decay_t<F>> e{f, count};
generator_iterator<std::decay_t<F>> b{std::forward<F>(f)};
return range( std::move(b), std::move(e) );
}
and this compiles:
std::vector<Object*> v1 = generate([](auto&&){ return new Object; }, 10).make_container();
Live example.
Related
I have a very basic 2D C++ container that relies on a single dimensional container (std::array or std::vector) and "advanced" indexing. This container is not expected to store many elements, not even 500. What would be the best approach in accessing its elements?
At first I was using int for indexing the elements directly while iterating the container. However, after reading a bit, posts such as this one made me switch to using std::size_t instead. (The switch was primarily about picking up good habits and not due to the requirements of my container. But other sources made me question whether it would be actually a good habit.)
As a result I had to readjust several for() loops to avoid underflow realated errors, e.g. when checking the values of elements next to one another, or when iteratin the elements backward in a row or a column. These changes in turn decreased the readability and made the indexing more error prone. (MyIiexperience is definitely a factor in this matter.)
What should I do?
stick with std::size_t
keep using int(while also restricting the size of my 2D storage to avoid unlikely overflows)
stick with range or iterator based loops by creating them for columns and rows (suggestions and links are welcome)
something else
Thank you in advance!
P.S.: Even C++20 functionality is welcomed!
std::ptrdiff_t is a signed std::size_t.
I use that. I have heard arguments that is what the standard should have used, at the cost of a single bit of maximum size.
Writing a stride-friendly iterator is a bit of a pain. Here is a sketch:
template<class T, class Stride=std::integral_constant<std::size_t, 1>>
struct stride_iterator {
using difference_type = std::ptrdiff_t;
using value_type = T;
using reference= T&;
private:
T* dataptr = nullptr;
Stride datastride = {};
T* data() const { return dataptr; }
T*& data() { return dataptr; }
Stride stride() const { return datastride; }
public:
explicit stride_iterator( T* ptr, Stride s ):
dataptr(ptr),
datastride{ std::move(s) }
{}
explicit stride_iterator( T* ptr ):
dataptr(ptr)
{}
stride_iterator():stride_iterator(nullptr) {}
stride_iterator(stride_iterator const&)=default;
stride_iterator& operator=(stride_iterator const&)& =default;
stride_iterator(stride_iterator &&)=default;
stride_iterator& operator=(stride_iterator &&)& =default;
T& operator*() const { return *data(); }
T* operator->() const { return data(); }
T& operator[](std::ptrdiff_t n) const {
return *(*this+n);
}
stride_iterator& operator+=( std::ptrdiff_t n )& {
data() += (n*stride());
return *this;
}
stride_iterator& operator-=( std::ptrdiff_t n )& {
data() -= (n*stride());
return *this;
}
friend stride_iterator operator+( std::ptrdiff_t rhs, stride_iterator lhs ) {
return std::move(lhs)+rhs;
}
friend stride_iterator operator+( stride_iterator lhs, std::ptrdiff_t rhs ) {
lhs += rhs;
return lhs;
}
friend stride_iterator operator-( stride_iterator lhs, std::ptrdiff_t rhs ) {
lhs += rhs;
return lhs;
}
stride_iterator& operator++() {
*this += 1;
return *this;
}
stride_iterator& operator--() {
*this -= 1;
return *this;
}
stride_iterator operator++(int) {
auto r = *this;
++*this;
return r;
}
stride_iterator operator--(int) {
auto r = *this;
--*this;
return r;
}
friend std::ptrdiff_t operator-( stride_iterator const& lhs, stride_iterator const& rhs ) {
return (lhs.data()-rhs.data())/stride();
}
friend bool operator<( stride_iterator const& lhs, stride_iterator const& rhs ) {
return lhs.data() < rhs.data();
}
friend bool operator<=( stride_iterator const& lhs, stride_iterator const& rhs ) {
return lhs.data() <= rhs.data();
}
friend bool operator>( stride_iterator const& lhs, stride_iterator const& rhs ) {
return lhs.data() > rhs.data();
}
friend bool operator>=( stride_iterator const& lhs, stride_iterator const& rhs ) {
return lhs.data() >= rhs.data();
}
friend bool operator==( stride_iterator const& lhs, stride_iterator const& rhs ) {
return lhs.data() == rhs.data();
}
friend bool operator!=( stride_iterator const& lhs, stride_iterator const& rhs ) {
return lhs.data() != rhs.data();
}
};
template<class It>
struct range {
It b, e;
It begin() const { return b; }
It end() const { return e; }
decltype(auto) operator[]( std::ptrdiff_t i ) const {
return b[i];
}
std::size_t size() const { return end()-begin(); }
bool empty() const { return end()==begin(); }
};
struct toy_matrix {
std::ptrdiff_t width = 1;
std::ptrdiff_t height = 1;
std::vector<int> data = std::vector<int>( 1 );
toy_matrix() = default;
toy_matrix( std::size_t w, std::size_t h ):width(w),height(h), data(w*h) {}
toy_matrix( std::size_t w, std::size_t h, std::initializer_list<int> il ):width(w),height(h), data(il) {
data.resize(w*h);
}
range<stride_iterator<int>> row( std::ptrdiff_t i ) {
int* ptr = data.data();
ptr += height * i;
return { stride_iterator<int>{ ptr }, stride_iterator<int>{ ptr + width } };
}
range<stride_iterator<int, std::ptrdiff_t>> column( std::ptrdiff_t i ) {
int* ptr = data.data();
ptr += i;
return { stride_iterator<int, std::ptrdiff_t>{ ptr, width }, stride_iterator<int, std::ptrdiff_t>{ ptr + height * width, width } };
}
range<stride_iterator<int>> operator[]( std::ptrdiff_t i ) {
return row(i);
}
int& operator()( std::ptrdiff_t x, std::ptrdiff_t y ) {
return (*this)[x][y];
}
};
Test code:
toy_matrix m{ 5, 4, {
1,2,3,4,5,
10,20,30,40,50,
100,200,300,400,500,
1000,2000,3000,4000,5000,
}};
for (auto x : m.column(0)) {
std::cout << x << "\n";
}
for (auto x : m.column(1)) {
std::cout << x << "\n";
}
for (auto x : m.column(2)) {
std::cout << x << "\n";
}
output:
1
10
100
1000
2
20
200
2000
3
30
300
3000
Live example.
Stroustrup prefers signed integer types unless one has a good reason to use an unsigned one.
Alexander Stepanov, the creator of the STL, preferred size_t, unsigned by definition, as the type to store containers' size.
So the difference is very subtle.
My personal opinion:
If you are a part of an organization, use their coding standards
Always avoid old-style for loops and prefer range-based for loops (for (auto x: vec) etc.). With this, there's no index, no room for a bug.
If you need the index inside the loop, prefer int and use C++20's std::ssize (signed size of a container).
Rationale:
std::ptrdiff_t is too lengthy to write :-) and you almost never have containers with more than 2 billion elements.
int in expressions is more natural and less error-prone
using just one unsigned variable inside a loop (or in any expression) often forces one to cast many other variables into unsigned type just to silence compiler warnings. The code gets ugly, very ugly.
signed integers are easier to optimize (as explained in the link included in the question)
That said, for years I used size_t (organization) or careless (int)v.size() (private code). std::ssize should have been added to the library ages ago.
How to make_shared count times, with different areas allocated without recur to a loop?
I have the following code:
for( unsigned int count = 0; count < demandedSize; ++count )
{
m_connectionList.push_back( std::make_shared< Foo >( m_ip, m_port ));
}
How to shorten this without a loop?
I know std::vector receaves a second argument as const T&, but in that case all shared_ptrs points to the same address (value is copied).
std::vector< std::shared_ptr<Foo> > vet( demandedSize, std::make_shared<Foo>( m_ip, m_port ) );
How to execute make_shared count times, with different areas allocated as result without recur to a loop
This should do the trick:
std::generate_n( back_inserter( m_connectionList ), demandedSize, [this]{
return std::make_shared< Foo >( m_ip, m_port ) );
});
Live Example on Coliru.
template<class X>
struct arrow_helper_t {
X x;
auto operator->()&& { return std::addressof(x); }
};
template<class X>
arrow_helper_t<X> arrow_helper(X&& x){ return {std::forward<X>(x)}; }
template<class F>
struct generator_iterator_t {
std::size_t i = 0;
F f;
generator_iterator_t()=default;
generator_iterator_t(generator_iterator_t const&)=default;
generator_iterator_t(generator_iterator_t &&)=default;
generator_iterator_t& operator=(generator_iterator_t const&)=default;
generator_iterator_t& operator=(generator_iterator_t &&)=default;
using iterator_category = std::input_iterator_tag;
using reference=decltype(std::declval<F const&>()(std::declval<std::size_t const&>()));
using value_type = std::decay_t<reference>;
using pointer = arrow_helper_t<reference>;
using difference_type = std::ptrdiff_t;
using self_t = generator_iterator_t;
friend bool operator!=(self_t const& lhs, self_t const& rhs) { return lhs.i != rhs.i; }
friend bool operator==(self_t const& lhs, self_t const& rhs) { return lhs.i == rhs.i; }
decltype(auto) operator*()const { return f(i); }
auto operator->() const { return arrow_helper(**this); }
self_t& operator++() { ++i; return *this; }
self_t operator++(int) { auto r = *this; ++i; return r; }
};
template<class F>
generator_iterator_t<F>
generator_iterator( F f, std::size_t i ) {
return {i, std::move(f)};
}
template<class F>
auto generator_range( F f, std::size_t i ) {
return std::make_pair(
generator_iterator(f, 0),
generator_iterator(f, i)
);
}
auto range = generator_range([&](auto){return std::make_shared< Foo >( m_ip, m_port );}, demandedSize);
m_connectionList.reserve( m_connectionList.size()+demandedSize );
m_connectionList.insert(m_connectionList.end(),
range.first, range.second
);
or somesuch. boost probably does it better.
live example.
I know that the C++ heavyweights are working on getting ranges into the language, or at least the standard library:
Eric Niebler discusses ranges on his blog
Interview with #BjarneStroustrup on his thoughts re C++17
ISO C++ standards committee (SC 22) proposal N4128 by Niebler, Parent and Sutton
To be fair - I haven't read through the official suggestion. I'm just a humble C++ programmer who wants to use simple range functionality. What should I do today rather than after C++17 to use, say, simple integer ranges with strides? Of course my requirements may expand as I start actually using ranges, but I'm still not after the fancier stuff and all sorts of corner cases. I think.
On the more restrictive side, I am working with a somewhat old environment due to compatibility needs (CUDA), so I need something to use with GCC 4.9.3 and its corresponding standard library version, and also something I can use in GPU code (not necessarily the same library/headers, but hopefully the same).
Well, should I roll my own limited-functionality integer range type, waiting for the formalities to settle - or should I go for one of the more heavy-weight alternatives (Niebler's "Ranges v3", Boost irange, etc.)?
Writing a simple "index" -- an input iterator that stores a type T and returns a type O=T via copy -- is easy.
What I call an index is an iterator over things that support advancement and comparison (including other iterators and integer-like things), and returns a copy of the contained object when dereferenced. It is also useful to generate ranges-over-iterators-into-ranges.
template<class T, class O=T>
struct index_t:
std::iterator<
std::input_iterator_tag,
O, std::ptrdiff_t, O*, O
>
{
T t;
explicit index_t(T&& tin):t(std::move(tin)){}
explicit index_t(T const& tin):t(tin){}
index_t()=default;
index_t(index_t&&)=default;
index_t(index_t const&)=default;
index_t& operator=(index_t&&)=default;
index_t& operator=(index_t const&)=default;
O operator*()const{ return t; }
O operator*(){ return t; }
O const* operator->()const{ return &t; }
O* operator->(){ return &t; }
index_t& operator++(){ ++t; return *this; }
index_t operator++(int){ auto r = *this; ++*this; return r; }
friend bool operator==(index_t const& lhs, index_t const& rhs) {
return lhs.t == rhs.t;
}
friend bool operator!=(index_t const& lhs, index_t const& rhs) { return !(lhs==rhs); }
};
template<class Scalar>
index_t<Scalar> index_to( Scalar s ) {
return index_t<Scalar>(std::move(s));
}
or somesuch. index_t<int> is a stride-less integer iterator.
If we want stride:
template<class T, class D=std::size_t>
struct strided {
T t;
D stride;
strided( T tin, D sin ):t(std::move(tin)), stride(std::move(sin)) {}
strided& operator++(){ t+=stride; return *this; }
strided operator++(int){ auto r = *this; ++*this; return r; }
operator T()&&{return std::move(t);}
operator T() const &{return t;}
friend bool operator==(strided const& lhs, strided const& rhs){
return lhs.t == rhs.t;
}
friend bool operator!=(strided const& lhs, strided const& rhs) { return !(lhs==rhs); }
};
template<class T, class D=std::size_t>
using strided_index_t = index_t<strided<T,D>, T>;
Now you just gotta write range_t<Iterator> (begin, end, empty, front, back, constructors).
template<class T>
strided_index_t<T> strided_index_to( T t, std::size_t d ) {
return strided_index_t<T>( {std::move(t), d} );
}
template<class It>
struct range_t {
It b,e;
using element_type = decltype( *std::declval<It>() );
It begin() const { return b; }
It end() const { return e; }
bool empty() const { return begin()==end(); }
element_type front() const { return *begin(); }
element_type back() const { return *std::prev(end()); }
};
template<class It>
range_t<It> range(It b, It e){
return {std::move(b), std::move(e)};
}
now we can make our index range:
template<class Scalar>
range_t<index_t<Scalar>> index_range( Scalar b, Scalar e ) {
return range( index_to(std::move(b)), index_to(std::move(e)) );
}
template<class Scalar>
range_t<strided_index_t<Scalar>> strided_index_range( Scalar b, Scalar e, std::size_t d ) {
return range( strided_index_to(std::move(b), d), strided_index_to(std::move(e), d) );
}
And now we test:
for (int i : index_range(0, 10))
std::cout << i << '\n';
for (int i : strided_index_range(0, 10, 2))
std::cout << i << '\n';
Similar objects also exist in boost and other range-based libraries.
Live example
As an aside,
for( auto it : index_to( begin(vec), end(vec) ) )
iterates over the iterators of vec in a range-based manner. Writing
for( auto it : iterators_into(vec) )
is also easy.
A common pattern in my current project is something like:
for(auto& row: matrix)
{
for(auto& col: row)
{
//insert simple operation here:
//return when condition is true
//increase counter when condition is true
//etc
}
}
As you can see the conditions would perfectly fit into some std::algorithm, but I don't really know how to iterate over this structure. Because of this most of the simple things, like counting the elements for which a condition is true, have several lines instead of one line.
Can you please suggest me a way of defining a matrix like data structure to make it friendly to use with std::algorithms?
boost has ways to merge multiple ranges into one range.
If you cannot use boost, you can write something like this:
template<class Iterator>
struct Range {
Iterator b_, e_;
Range( Iterator b, Iterator e ):b_(b), e_(e) {}
Iterator begin() const { return b_; }
Iterator end() const { return e_; }
bool empty() const { return begin() == end(); }
template<class C>
static auto adl_begin(C&& c) {
using std::begin;
return begin( std::forward<C>(c) );
}
template<class C>
static auto adl_end(C&& c) {
using std::end;
return end( std::forward<C>(c) );
}
template<class C>
explicit Range(C&& c):
Range(adl_begin(std::forward<C>(c)), adl_end(std::forward<C>(c)))
{}
Range():b_(), e_() {}; // Range of pointers should be null null just in case
Range( Range const& ) = default;
Range( Range && ) = default;
~Range() = default;
Range& operator=(Range const&)=default;
Range& operator=(Range &&)=default;
friend bool operator==( Range const& lhs, Range const& rhs ) {
return lhs.b_ == rhs.b_ && lhs.e_ == rhs.e_;
}
friend bool operator!=( Range const& lhs, Range const& rhs ) {
return !( lhs == rhs );
}
};
the above is a pretty simple Range template that lets you store pairs of iterators in a bundle that can be iterated over and thought about as a single unit. boost has one of those as well, probably better written.
Next, an iterator over two nested ranges:
template<class Outer, class Inner>
struct bi_iterator:std::iterator<
std::forward_iterator_tag,
typename std::iterator_traits<Inner>::value_type
// in theory add more, but I won't bother
> {
using value_type = typename std::iterator_traits<Inner>::value_type;
Range<Outer> outer;
Range<Inner> inner;
explicit bi_iterator( Range<Outer> out ):outer(out), inner(advance())
{}
friend bool operator==( bi_iterator const& lhs, bi_iterator const& rhs ) {
if (lhs.outer != rhs.outer) return false;
if (lhs.outer.empty()) return true;
return lhs.inner == rhs.inner;
}
friend bool operator!=( bi_iterator const& lhs, bi_iterator const& rhs ) {
return !(lhs==rhs);
}
private:
Range<Inner> advance() {
if (outer.empty()) return;
inner = Range<Inner>( *outer.begin() );
rectify();
return inner;
}
void rectify() {
if (!inner.empty()) return;
if (outer.empty()) return;
outer = {std::next(outer.begin()), outer.end()};
inner = advance();
}
public:
value_type& operator*() { return *inner.begin(); }
bi_iterator operator++(int) {
bi_iterator retval = *this;
++(*this);
return retval;
}
bi_iterator& operator++() {
inner = { std::next(inner.begin()), inner.end() };
rectify();
return *this;
};
};
template<class Outer, class Inner>
Range<bi_iterator<Outer,Inner>> bi_range_helper( Range<Outer> out ) {
return { bi_iterator<Outer,Inner>(out), bi_iterator<Outer,Inner>({out.end(), out.end()}) };
}
template<class Container>
auto bi_range( Container&& c ) {
using std::begin; using std::end;
auto b = begin(c);
auto e = end(c);
using Outer = decltype(b);
using Inner = typename std::decay<decltype(begin(*b))>::type;
return bi_range_helper<Outer,Inner>( {b,e} );
}
Then:
auto bi = bi_range( matrix );
for( auto&& element: bi ) { /* stuff */ }
should iterate over the 2nd dimension of matrix, and
using std::begin; using std::end;
auto b = begin(bi);
auto e = end(bi);
should be some <algorithms> compatible forward iterators into the elements in the 2nd dimension of matrix.
Note that there may be some errors above, I wrote it without any tests or even compiling it.
(Aside: always use std::begin and std::end in ADL-compatible contexts, hence the using std::begin clauses).
If you get the above to work, a fun project: make nary_iterator that builds recursive bi_iterator types to chain any amount of depth. For an advanced problem, do it without chaining bi_iterator.
Note that my bi_iterator is going to be inferior to the boost version (I forget what it is called) in many ways, as I just whipped it out, and boost undergoes review.
Are there situations in which std::sort fails?
I've got a std::vector<KeyValPair<T>> queue with which I do the following
std::sort(queue.begin(), queue.end());
std::pair<iterator, iterator> match =
std::equal_range(queue.begin(), queue.end(), cost);
Exactly that. And then sometimes, not always, I get a "sequence not ordered" error.
The documentation describes sort and equal_range as using the same comparison functions, so I am confused how the vector could become unordered.
The vector type is the following class with custom comparison operators.
template<typename T>
class KeyValPair: public std::pair<double, T>
{
public:
KeyValPair(double d, T t): std::pair<double, T>(d, t){};
bool operator<(const KeyValPair<T>& rhs) const
{
return first < rhs.first;
}
bool operator==(const KeyValPair<T>& rhs) const
{
return second == rhs.second;
}
};
template<typename T>
bool operator< (const KeyValPair<T>& lhs, const double& rhs) {return lhs.first < rhs;};
template<typename T>
bool operator< (const double& lhs, const KeyValPair<T>& rhs) {return lhs < rhs.first;};
Could the comparison function be failing somehow? What else can cause this error?
As first psychically detected by #ecatmur, your problem is you are using < on doubles, and one or more of your doubles is a NaN.
A safe double ordering follows:
struct safe_double_order {
bool operator()(double lhs, double rhs) const {
if ((lhs != lhs) || (rhs != rhs)) // NaN detector
return (lhs!=lhs)>(rhs!=rhs); // order NaN less than everything, including -infinity
return lhs < rhs;
}
};
Next, we can write a key-sorter:
template<class K, class O=std::less<K>>
struct key_sorter {
struct helper {
K const& k;
helper( K const& o ):k(o) {}
template<typename V>
helper( std::pair<K, V> const& o ):k(o.first) {}
bool operator<( helper const& o ) const {
return O{}( k, k.o );
}
};
bool operator()( helper lhs, helper rhs ) const {
return lhs < rhs;
}
};
which passed a key-type and an optional ordering functor lets you search/sort std::pair<Key,?> with Key types directly.
std::vector< std::pair<double, X> > vec;
std::sort( vec.begin(), vec.end(), key_sorter<double, safe_double_order>{} );
auto match = std::equal_range( vec.begin(), vec.end(), value, key_sorter<double, safe_double_order>{} );
There are some C++11isms above, but the general design should be clear if you are using C++03.