Why std::swap does not work with std::bitset<n> content? - c++

Consider this unit test:
std::bitset<8> temp( "11010100" );
reverseBitSet( temp );
CPPUNIT_ASSERT( temp == std::bitset<8>( "00101011" ) );
This implementation works:
template<size_t _Count> static inline void reverseBitSet( std::bitset<_Count>& bitset )
{
bool val;
for ( size_t pos = 0; pos < _Count/2; ++pos )
{
val = bitset[pos];
bitset[pos] = bitset[_Count-pos-1];
bitset[_Count-pos-1] = val;
}
}
While this one does not:
template<size_t _Count> static inline void reverseBitSet( std::bitset<_Count>& bitset )
{
for ( size_t pos = 0; pos < _Count/2; ++pos )
{
std::swap( bitset[pos], bitset[_Count-pos-1] );
}
}
Result is "11011011" instead of "00101011"
Why is swap doing it wrong?

This:
std::swap( bitset[pos], bitset[_Count-pos-1] );
should actual fail to compile. operator[] for a std::bitset doesn't return a reference, it returns a proxy object. That proxy object isn't an lvalue, so it cannot bind to the T& in std::swap. I'm assuming the fact that it compiles at all means that you're using MSVC which has an extension that allows binding temporaries to non-const references - at which point you're probably just swapping the proxies and not what the proxies are actually referring to.
Side-note: The name _Count is reserved by the standard, as is any other name which begins with an _ followed by a capital letter.

Related

Using range::find on a view

I'd like to rangify the following code, which checks for the first occurance of a sequence of unique characters:
bool hasOnlyUniqueElements( auto& data ) {
std::unordered_set<char> set;
for( auto& value : data )
set.emplace( value );
return set.size() == data.size();
}
int64_t getStartPacketMarker( const std::string& data, int64_t markerSize ) {
for( int64_t i = 0; i < data.size() - markerSize; i++ )
{
std::string_view packet( data.begin() + i, data.begin() + i + markerSize );
if( hasOnlyUniqueElements( packet ) )
return i + markerSize;
}
return -1;
}
I came up with the following, that uses ranges but is only marginally better:
int64_t getStartPacketMarker( const std::string& data, int64_t markerSize ) {
int64_t idx = 0;
for( auto packet : data | ranges::views::sliding( markerSize ) ) {
if( hasOnlyUniqueElements( packet ) )
return idx + markerSize;
idx++;
}
return -1;
}
This should be a simple find operation, but I couldn't make it work and couldn't find any examples on find being used on views. Is it possible to use find on views?
Yes, you can use find on views. However, in your case, you should use find_if since you are checking against a predicate function:
auto view = data | std::views::slide(markerSize);
auto it = std::ranges::find_if(
view, somePredicate
);
return it == view.end() ? -1 : it - view.begin();
However, since your predicate function has an auto-deduced parameter, you can't get the function pointer of it directly, and you would need to wrap it in a lambda instead:
auto view = data | std::views::slide(markerSize);
auto it = std::ranges::find_if(
view, [](const auto& v) { return hasOnlyUniqueElements(v); }
);
return it == view.end() ? -1 : it - view.begin();
Besides using std::ranges::find_if on the range you could skip the ´for´ loop that builds the set in hasOnlyUniqueElements using std::unique:
auto set = data;
std::unique(std::sort(set));

Converting a for loop to use std::transform instead

I'm working on a function and it currently works as is.
void ceasarShift( CeasarText& text, int amount ) {
// Bound amount to the number of characters in the alphabet
amount %= 26;
for ( std::size_t i = 0; i < text._originalText.length(); i++ ) {
char c = text._originalText[i] + amount;
text._shiftedText += c;
}
}
The class that this function takes is a simple class that has 2 std::string member variables. When this class is passed by reference where this is a friend function to that class, it takes the original string that is already set and uses that to populate the shifted string which is empty before this function sees it. When the for loop is done, the function is finished and the class object is returned back by reference with a newly updated shifted string and the original is unmodified.
I was thinking of maybe using std::transform and a lambda to do the same task. This is what I have tried.
void ceasarShift( CeasarText& text, int amount ) {
// Bound amount to the number of characters in the alphabet
amount %= 26;
/*for ( std::size_t i = 0; i < text._originalText.length(); i++ ) {
char c = text._originalText[i] + amount;
text._shiftedText += c;
}*/
std::transform( text._originalText.begin(), text._originalText.end(),
text._shiftedText.begin(),
[amount]( unsigned char c ) -> unsigned char { return c + amount; }
);
}
And I end up getting a Debug Assertion Failed! Window message Expression: cannot seek string iterator past end
I'm wondering if my lambda is wrong or if I need to use something else other than std::transform.
Edit
I have also tried this and this works like the first loop:
{
amount %= 26;
for ( auto& c : text._originalText )
text._shiftedText += (c + amount);
}
I just can not seem to get the lambda to work properly as the predicate to std::transform.
The problem is not your lambda. The difference between your two snippets, is that your for loop appends elements to your string, using operator+=, but your transform assumes that the elements already exist. If you want to append to the string with transform, then you will need to use an insert iterator. Specifically a back insert iterator. So instead of passing text._shiftedText.begin(), pass std::back_inserter(text._shiftedText).
std::transform( text._originalText.begin(), text._originalText.end(),
std::back_inserter(text._shiftedText),
[amount]( unsigned char c ) -> unsigned char { return c + amount; }
);
According to this link, The behavior of std::transform is equivalent to:
template <class InputIterator, class OutputIterator, class UnaryOperator>
OutputIterator transform (InputIterator first1, InputIterator last1,
OutputIterator result, UnaryOperator op)
{
while (first1 != last1) {
*result = op(*first1); // or: *result=binary_op(*first1,*first2++);
++result; ++first1;
}
return result;
}
which means the container of OutputIterator should reserve enough space, otherwise, it will out of range when ++result

Placement New and Perfect Forwarding

I have the following code that intends to create an array, but without default initialization of its objects. I would like to forward perfectly to placement new, which seems to happen, but I find that the objects' destructor is called inside the emplace function.
#include <iostream>
#include <memory> // std::uninitialized_copy, std::allocator...
#include <utility> // std::move...
#include <bitset>
struct Int {
int i;
Int ( ) : i ( -1 ) { std::cout << "default constructed\n"; }
Int ( const int i_ ) : i ( i_ ) { std::cout << i << " constructed\n"; }
Int ( Int && int_ ) : i ( std::move ( int_.i ) ) { std::cout << i << " move constructed\n"; }
Int ( const Int & int_ ) : i ( int_.i ) { std::cout << i << " copy constructed\n"; }
~Int ( ) { std::cout << i << " destructed\n"; i = -1; }
};
template <typename T, size_t S = 64>
class NoInitArray {
std::bitset<S> m_used;
T *m_array = reinterpret_cast < T* > ( ::operator new ( sizeof ( T ) * S ) );
public:
T const &operator [ ] ( const size_t idx_ ) const {
return m_array [ idx_ ];
}
NoInitArray ( ) { }
~NoInitArray ( ) {
for ( size_t idx = 0; idx < S; ++idx ) {
if ( m_used [ idx ] ) {
reinterpret_cast< const T* > ( m_array + idx )->~T ( );
}
}
}
template<typename ...Args>
void emplace ( const size_t idx_, Args &&... value_ ) {
std::cout << "start emplace\n";
m_used [ idx_ ] = 1;
new ( m_array + idx_ ) T ( std::forward<T> ( value_ ) ... );
std::cout << "end emplace\n";
}
};
int main ( ) {
NoInitArray<Int> nia;
nia.emplace ( 0, 0 );
nia.emplace ( 1, 1 );
std::cout << nia [ 1 ].i << std::endl;
nia.emplace ( 2, 2 );
return 0;
}
The result of running this program is as follows:
start emplace
0 constructed
0 move constructed
0 destructed
end emplace
start emplace
1 constructed
1 move constructed
1 destructed
end emplace
1
start emplace
2 constructed
2 move constructed
2 destructed
end emplace
0 destructed
1 destructed
2 destructed
It shows that the objects are constructed once and destructed twice (which obviously is UB), once inside the emplace function, and then once at destruction of the NoInitArray.
The question is "Why is the destructor of my Int object called inside the emplace function"?
Compiler, latest Clang/LLVM on Windhoze.
EDIT1: I've added move and copy constructors to the Int struct, now the count matches, i.e. 2 constructions and 2 destructions.
EDIT2: Changing the Placement New line from new ( m_array + idx_ ) T ( std::forward<T> ( value_ ) ... ); to new ( m_array + idx_ ) T ( value_ ... ); avoids the superfluous construction/destruction, without the need for a move constructor.
EDIT3: Just for future readers. As per above, the ~NoInitArray() leaks memory. Calling delete on m_array is bad news as well as this calls (in Clang/LLVM) the destructor of m_array [ 0 ] (but as far as I've understood now, that is in no way guaranteed, i.e. UB). std::malloc/std::free seems to be the way to go, but some say that if you do that all hell will break lose, and one may lose a leg.
"It shows that the objects are constructed once and destructed twice" is not true. The output X move constructed should be included as one construction so the constructions are twice.
The line
new ( m_array + idx_ ) T ( std::forward<T> ( value_ ) ... );
should be
new ( m_array + idx_ ) T ( std::forward<Args&&> ( value_ )... );
std::forward<T>(value_) calls the constructor when T=Int, and this temporary object is moved, so there is an extra move constructor call.
EDIT
In your edit 2 you replace the line without std::forward anymore. In this case, OK, but the differences emerge when you call the emplace like this
nia.emplace ( 0, Int(0) );
Without std::forward, new T(value_...) would call the copy constructor, while new T(std::forward<Args&&>(value_)...) would call the move constructor.
EDIT-2
It should be new T(std::forward<Args>(value_)...). Thanks to #Constantin Baranov.
I think the constructor and destructor are called in the step: std::forward<T> ( value_ ) in new ( m_array + idx_ ) T ( std::forward<T> ( value_ ) ... ).
The std::forward<T>(value_) will create a temp value T.

Elegant way to iterate conditionally forwards or reversed

I have to process an std::vector either forwards or in reverse, depending upon a boolean flag. What's the most elegant way to accomplish this? Before needing to do it in reverse I had:
BOOST_FOREACH(const CType &foo, vec) {
...
}
However, now I have the horrendous-looking:
for (int i=undoing ? (vec.size()-1) : 0; undoing ? (i >= 0) : (i < vec.size()); undoing ? (i--) : (i++)) {
const CType &foo = vec[i];
...
}
Is there a better way?
I don't know that people would call it elegant, but there's:
auto do_it = [](const CType& elem)
{
...
};
if (iterate_forward) {
std::for_each(vec.begin(), vec.end(), do_it);
}
else {
std::for_each(vec.rbegin(), vec.rend(), do_it);
}
Add a template function that works with either the forward iterators or reverse iterators. Call the function using the appropriate iterator based on the value of undoing.
template <typename Iterator>
void doStuff(Iterator iter, Iterator end)
{
for ( ; iter != end; ++iter )
{
// Do stuff
}
}
if ( undoing )
{
doStuff(vec.rbegin(), vec.rend());
}
else
{
doStuff(vec.begin(), vec.end());
}
How about keeping the loop running as it is from 0 to vector.size, but reading the array in the direction you need.
int idx;
for (int i =0; i < vec.size(); i ++)
{
if (undoing) // assuming going forward
idx = i;
else // going backwards
idx = vec.size() - i - 1;
const CType &foo = vec[idx];
}
You may also use Boost.Range-based solution. It's similar to the one using STL algorithms, already proposed.
#include <boost/range/adaptor/reversed.hpp>
#include <boost/range/algorithm/for_each.hpp>
// In C++11 lambda expression can be used instead
struct my_fun
{
void operator()(const CType& elem) const
{
/*...*/
}
};
/*...*/
using namespace boost::adaptors;
if ( iterate_forward )
boost::for_each(my_vect, my_fun());
else
boost::for_each(my_vect | reversed, my_fun());

simple list in c++

explicit list(
const A& Al = A( )
);
explicit list(
size_type n,
const T& v = T( ),
const A& Al = A( )
);
list(
const list& x
);
list(
const_iterator First,
const_iterator Last,
const A& Al = A( )
);
#include <list>
using namespace std;
list<Node> my_list;
int index = 0;
for ( list<Node>::iterator cursor = my_list.begin();
it!= my_list.end(); ++ cursor, ++ index ) {
cout << "index: " << index << “ value: “ << cursor->data() << endl;
}
At least based on what you have here, the problem isn't with how you traverse the list -- it's with using a list at all. You're asking for random access to the data, which means you should probably be using something like a vector or a deque instead of a list.
I really can't tell what this is trying to do, but you have a possible segfault in your inner loop:
for ( cursor = head_ptr; cursor !=NULL ||count<i; cursor=cursor->link() )
{
count++;
}
Your termination condition indicates that if count < i, you would keep looping even if cursor == NULL; when cursor=cursor->link() executes, you would try to dereference NULL.
Perhaps you meant cursor !=NULL && count<i ?