I'm trying to create a macro to replace the for-loop
I want it to work like this:
f(var, start, Eend)
where var is the name of the loop variable, the start is the value where it begins and end, the value where it stops. The E is a symbol that can exist or not. If it exist, it is =
my macro is actually like this:
#define f(var, s, e) for(int var = s, kx = (s<e? 1 : -1); var != e; var += kx)
but this definition cannot afford = yet, so I want to extend it like this:
f(i, 10, =15) cout<<" "<<i;
output: 10 11 12 13 14 15
My question is if it's possible to remove the first char of the Eend argument of macro.
I can discover if it's equal using
#Eend[0] == '='
but after I cant use Eend to compare with s and find out if I must use ++ or --
This is what I want:
#define f(var, s, Eend)
for(int var = s, kx = s<end? 1:-1, LIM = #Eend[0] == '='? end+kx : end; var!=end; var += kx)
where end is Eend without the '=' (if it exists)
For your macro question you can simply define two macros, with slightly different (hopefully mnemonic) names.
E.g., if I understand the intention correctly,
#define xf(var, s, e) for(int var = s, kx = (s<e? 1 : -1); var != e; var += kx)
#define f(var, s, e) for(int var = s, kx = (s<e? 1 : -1), e2 = e + kx; var != e2; var += kx)
If the redundancy of that is not palatable, then you can express them in terms of a third common implementation macro.
Doing this without a macro is more work, but you only have to do the definition work once.
And you avoid possible name collisions for the macro.
E.g. it can go like this:
enum From { from };
enum To { to };
enum To_before { to_before };
class Sequence
{
private:
int first_;
int after_;
int delta_;
public:
class Iter
{
friend class Sequence;
private:
Sequence const* p_seq_;
int current_;
Iter( Sequence const& seq )
: p_seq_( &seq )
, current_( seq.first_ )
{}
Iter( Sequence const& seq, int const current )
: p_seq_( &seq )
, current_( current )
{}
public:
friend auto operator==( Iter const& a, Iter const& b )
-> bool
{ return a.current_ == b.current_; } // UB if not same sequence.
friend auto operator!=( Iter const& a, Iter const& b )
-> bool
{ return a.current_ != b.current_; }
auto operator*() const
-> int
{ return current_; }
auto operator++()
-> Iter&
{
current_ += p_seq_->delta_;
return *this;
}
auto operator++( int )
-> Iter
{
Iter result{ *this };
current_ += p_seq_->delta_;
return result;
}
};
auto begin() const -> Iter { return Iter{ *this }; }
auto end() const -> Iter { return Iter{ *this, after_ }; }
Sequence( int const first, int const last, bool inclusive = true )
: first_( first )
, after_( last )
, delta_( first <= last? 1 : -1 )
{ if( inclusive ) { after_ += delta_; } }
Sequence( From, int const first, To, int const last )
: Sequence( first, last, true )
{}
Sequence( From, int const first, To_before, int const last )
: Sequence( first, last, false )
{}
};
#include <iostream>
using namespace std;
auto main()
-> int
{
using Seq = Sequence;
for( int const i : Seq{ from, 10, to, 15 } ) { cout << i << ' '; }
cout << endl;
for( int const i : Seq{ from, 15, to, 10 } ) { cout << i << ' '; }
cout << endl;
cout << endl;
for( int const i : Seq{ from, 10, to_before, 15 } ) { cout << i << ' '; }
cout << endl;
for( int const i : Seq{ from, 15, to_before, 10 } ) { cout << i << ' '; }
cout << endl;
}
Related
This is a very specific issue and is a bit long to explain, so please bear with me as I try to summarize this as best I can.
I create 2 user types, the first is used inside the second :
struct mySubType {
int val;
mySubType () {}
mySubType ( int _val) : val(_val){}
bool operator!=(const mySubType& rhs) const { return val != rhs.val; }
};
struct myType {
mySubType start;
mySubType stop;
myType () {}
myType (mySubType _start, mySubType _stop) : start(_start), stop(_stop) {}
};
In main(), I create a vector of unique_ptr to myType and fill it as such :
vector<unique_ptr<myType>> v;
for (int i = 0; i < 10; ++i)
v.push_back( unique_ptr<myType>(new myType( mySubType(i), mySubType(i+1))) );
So the val of start and stop for each element is as follows :
start:0 stop:1
start:1 stop:2
start:2 stop:3
start:3 stop:4
start:4 stop:5
start:5 stop:6
start:6 stop:7
start:7 stop:8
start:8 stop:9
start:9 stop:10
start should always be the same as previous stop (this is the case in this example). To check this, I tried the following :
for (auto it = v.begin(); it != --v.end(); )
{
if ((*it)->stop != (*(++it))->start)
cout << "1";
}
To my surprise, the output was : 111111111, all different when they should be all equal.
I tried a few other things to try and understand the source of the error. I replaced the inside of the loop with
mySubType stop = (*it)->stop;
mySubType next_start = (*(++it))->start;
if (stop != next_start)
cout << "2";
and then
if ((*it)->stop.val != (*(++it))->start.val)
cout << "3";
Neither of those printed anything (all tests were correctly solved as equal).
This only happens when using unique_ptr (vector<myType> does not have the same issue). I also tried using post-increment but I get the exact same result.
Does anyone have a clue why this happens ?
I know there are a lot of ways to work around this issue (the 2 above for example). What I'm interested in is why this behaviour happens.
The expression in the if statement
if ((*it)->stop != (*(++it))->start)
has undefined behavior.
It seems you mean the following loop
#include <iterator>
// ...
for (auto it = v.begin(); it != v.end(); ++it )
{
auto next = std::next( it );
if ( next != v.end() && (*it)->stop != (*( next ))->start)
std::cout << "1";
}
Instead of the for loop you could use the standard algorithm std::adjacent_find. For example
#include <iostream>
#include <memory>
#include <vector>
#include <iterator>
#include <algorithm>
struct mySubType {
int val;
mySubType () {}
mySubType ( int _val) : val(_val){}
bool operator!=(const mySubType& rhs) const { return val != rhs.val; }
};
struct myType {
mySubType start;
mySubType stop;
myType () {}
myType (mySubType _start, mySubType _stop) : start(_start), stop(_stop) {}
};
int main()
{
std::vector<std::unique_ptr<myType>> v;
for (int i = 0; i < 10; ++i)
v.push_back( std::unique_ptr<myType>(new myType( mySubType(i), mySubType(i+1))) );
auto it = std::adjacent_find( std::begin( v ), std::end( v ),
[]( const auto &left, const auto &right )
{
return left->stop != right->start;
} );
if ( it != std::end( v ) ) std::cout << "there is an error\n";
else std::cout << "The sequence is correct\n";
}
The program output is
The sequence is correct
I would like to translate the following traditional for loop into a C++11 for-each loop without extra looping constructs:
int a[] = { 5, 6, 7, 8, 9, 10 };
int b[] = { 50, 60, 70, 80, 90, 100 };
// Swap a and b array elements
for (int i = 0; i < sizeof(a)/sizeof(a[0]); i++)
{
a[i] ^= b[i]; b[i] ^= a[i]; a[i] ^= b[i];
}
Does there exist any way by which it is possible to provide more than one variable in the C++11 for-each loop like:
for (int i, int j : ...)
There is no built-in way to do this. If you can use Boost, boost::combine will work for iterating two (or more) ranges simultaneously (Does boost offer make_zip_range?, How can I iterate over two vectors simultaneously using BOOST_FOREACH?):
for (boost::tuple<int&, int&> ij : boost::combine(a, b)) {
int& i = boost::get<0>(ij);
int& j = boost::get<1>(ij);
// ...
}
Unfortunately accessing the elements within the tuple elements of the zipped range is highly verbose. C++17 will make this much more readable using structured binding:
for (auto [&i, &j] : boost::combine(a, b)) {
// ...
}
Since you don't need to break out of the loop or return from the enclosing function, you could use boost::range::for_each with the body of your loop as a lambda:
boost::range::for_each(a, b, [](int& i, int& j)
{
// ...
});
zip or combine ranges are common in many range libraries.
Writing one strong enough for a for(:) loop isn't hard however.
First we write a basic range type:
template<class It>
struct range_t {
It b,e;
It begin() const{ return b; }
It end() const{ return e; }
range_t without_front( std::size_t count = 1 ) const {
return {std::next(begin()), end()};
}
bool empty() const { return begin()==end(); }
};
template<class It>
range_t<It> range( It b, It e ) { return {b,e}; }
template<class C>
auto range( C& c ) {
using std::begin; using std::end;
return range( begin(c), end(c) );
};
Then we write an iterator that works with ranges (easier than with iterators):
template<class R1, class R2>
struct double_foreach_iterator {
R1 r1;
R2 r2;
void operator++() { r1 = r1.without_front(); r2 = r2.without_front(); }
bool is_end() const { return r1.empty() || r2.empty(); }
auto operator*()const {
return std::tie( *r1.begin(), *r2.begin() );
}
using self=double_foreach_iterator;
auto cur() const {
return std::make_tuple( r1.begin(), r2.begin() );
}
friend bool operator==( self const& lhs, self const& rhs ) {
if (lhs.is_end() || rhs.is_end())
return lhs.is_end() == rhs.is_end();
return lhs.cur() == rhs.cur();
}
friend bool operator!=( self const& lhs, self const& rhs ) {
return !(lhs==rhs);
}
};
now we double iterate:
template<class A, class B>
auto zip_iterate(
A& a, B& b
) {
auto r1 = range(a);
auto r2 = range(b);
auto r1end = range(r1.end(), r1.end());
auto r2end = range(r2.end(), r2.end());
using it = double_foreach_iterator<decltype(r1), decltype(r2)>;
return range( it{r1, r2}, it{r1end, r2end} );
}
which gives us:
for (auto tup : zip_iterate(a, b)) {
int& i = std::get<0>(tup);
int& j = std::get<1>(tup);
// ...
}
or in C++17:
for (auto&& [i, j] : zip_iterate(a, b)) {
// ...
}
My zip iterate does not assume the two containers are of the same length, and will iterate to the length of the shorter one.
live example.
Just for fun.
The following isn't intended to be a serious answer to the question but just an exercise to try to understand the potentiality of C++11 (so, please, be patient).
The following is an example of a class (a draft of a class) that receive a couple of container (with size() method), with the same size (exception otherwise), and of a custom iterator that return a std::pair of std::reference_wrapper to n-position elements.
With a simple use example that show that it's possible to change the value in the starting containers.
Doesn't work with old C-style arrays but works with std::array. We're talking about C++11 so I suppose we could impose the use of std::array.
#include <array>
#include <vector>
#include <iostream>
#include <functional>
template <typename T1, typename T2>
class pairWrapper
{
public:
using V1 = typename std::remove_reference<decltype((T1().at(0)))>::type;
using V2 = typename std::remove_reference<decltype((T2().at(0)))>::type;
using RW1 = std::reference_wrapper<V1>;
using RW2 = std::reference_wrapper<V2>;
class it
{
public:
it (pairWrapper & pw0, std::size_t p0): pos{p0}, pw{pw0}
{ }
it & operator++ ()
{ ++pos; return *this; }
bool operator!= (const it & it0)
{ return pos != it0.pos; }
std::pair<RW1, RW2> & operator* ()
{
static std::pair<RW1, RW2>
p{std::ref(pw.t1[0]), std::ref(pw.t2[0])};
p.first = std::ref(pw.t1[pos]);
p.second = std::ref(pw.t2[pos]);
return p;
}
private:
std::size_t pos;
pairWrapper & pw;
};
it begin()
{ return it(*this, 0U); }
it end()
{ return it(*this, len); }
pairWrapper (T1 & t10, T2 & t20) : len{t10.size()}, t1{t10}, t2{t20}
{ if ( t20.size() != len ) throw std::logic_error("no same len"); }
private:
const std::size_t len;
T1 & t1;
T2 & t2;
};
template <typename T1, typename T2>
pairWrapper<T1, T2> makePairWrapper (T1 & t1, T2 & t2)
{ return pairWrapper<T1, T2>(t1, t2); }
int main()
{
std::vector<int> v1 { 1, 2, 3, 4 };
std::array<long, 4> v2 { { 11L, 22L, 33L, 44L } };
for ( auto & p : makePairWrapper(v1, v2) )
{
std::cout << '{' << p.first << ", " << p.second << '}' << std::endl;
p.first += 3;
p.second += 55;
}
for ( const auto & i : v1 )
std::cout << '[' << i << ']' << std::endl;
for ( const auto & l : v2 )
std::cout << '[' << l << ']' << std::endl;
return 0;
}
p.s.: sorry for my bad English
I have the following piece of code. The code creates a vector Dataset, each element of which is a vector. It also creates a vector S.
I want to check which vector of Dataset contain vector of S. Apparently I am doing something wrong, because for the following example,
Dataset is:
a b c
a d
a b d
and S:
a b
it should print: 0 2
and for me it prints: 0 1 2
#include <iostream>
#include <fstream>
#include <sstream>
#include <string.h>
#include <string>
#include <time.h>
#include <vector>
#include <algorithm>
using namespace std;
class StringRef
{
private:
char const* begin_;
int size_;
public:
int size() const { return size_; }
char const* begin() const { return begin_; }
char const* end() const { return begin_ + size_; }
StringRef( char const* const begin, int const size )
: begin_( begin )
, size_( size )
{}
bool operator<(const StringRef& obj) const
{
return (strcmp(begin(),obj.begin()) > 0 );
}
};
/************************************************
* Checks if vector B is subset of vector A *
************************************************/
bool isSubset(std::vector<StringRef> A, std::vector<StringRef> B)
{
std::sort(A.begin(), A.end());
std::sort(B.begin(), B.end());
return std::includes(A.begin(), A.end(), B.begin(), B.end());
}
vector<StringRef> split3( string const& str, char delimiter = ' ' )
{
vector<StringRef> result;
enum State { inSpace, inToken };
State state = inSpace;
char const* pTokenBegin = 0; // Init to satisfy compiler.
for(auto it = str.begin(); it != str.end(); ++it )
{
State const newState = (*it == delimiter? inSpace : inToken);
if( newState != state )
{
switch( newState )
{
case inSpace:
result.push_back( StringRef( pTokenBegin, &*it - pTokenBegin ) );
break;
case inToken:
pTokenBegin = &*it;
}
}
state = newState;
}
if( state == inToken )
{
result.push_back( StringRef( pTokenBegin, &str.back() - pTokenBegin ) );
}
return result;
}
int main() {
vector<vector<StringRef> > Dataset;
vector<vector<StringRef> > S;
ifstream input("test.dat");
long count = 0;
int sec, lps;
time_t start = time(NULL);
cin.sync_with_stdio(false); //disable synchronous IO
for( string line; getline( input, line ); )
{
Dataset.push_back(split3( line ));
count++;
};
input.close();
input.clear();
input.open("subs.dat");
for( string line; getline( input, line ); )
{
S.push_back(split3( line ));
};
for ( std::vector<std::vector<StringRef> >::size_type i = 0; i < S.size(); i++ )
{
for(std::vector<std::vector<StringRef> >::size_type j=0; j<Dataset.size();j++)
{
if (isSubset(Dataset[j], S[i]))
{
cout << j << " ";
}
}
}
sec = (int) time(NULL) - start;
cerr << "C++ : Saw " << count << " lines in " << sec << " seconds." ;
if (sec > 0) {
lps = count / sec;
cerr << " Crunch speed: " << lps << endl;
} else
cerr << endl;
return 0;
}
Your StringRef type is dangerous because it contains a const char * pointer, but no concept of ownership. So the pointer could be invalidated at some point after the object is constructed.
And indeed this is what happens here: You have a single string (line) and create StringRefs with pointers to its internal data. When the string is later modified, these pointers are invalidated.
You should create a vector<std::string> instead to prevent this problem.
I am in my first year of c++ at university and in some days i have exam.
I work hard for this exam not only to succeed but to succeed with the best mark.
In this code that I post I have to make a bidirectional map which i was able to do and some other functions for it.
The problem comes when i try to make a copy constructor for this bidirectional map.
I know it is a little shameful to come to you guys with this minor problem but I last give a try.
If someone of you has patience to help me i will be very happy to succeed with high mark at my c++ exam.
So here is the header where i create a bidirectional map.This contains 2 maps: one stores the key and the value and other stores the value like key and the first key like the value. The problem comes when i have to do a copy constructor and I not have the optimal knowledge to do this.
#ifndef BIMAP_H_INCLUDED
#define BIMAP_H_INCLUDED
#include<map>
#include <utility>
template <class T>
class BidirectionalMap
{
public:
BidirectionalMap(){};
BidirectionalMap(typename std::multimap<T,T>::iterator beg, typename std::multimap<T,T>::iterator end)
{
m1.insert(beg,end
}
void insert(T a, T b)
{
m1.insert(std::pair<T,T> (a,b));
m2.insert(std::pair<T,T> (b,a));
}
BidirectionalMap& operator =(const BidirectionalMap &c)
{
m1=c.m1;
m2=c.m2;
return *this;
}
const T& at(const T &a) const
{
if(m2.find(a)!=m2.end()) return m2.at(a);
else return m1.at(a);
}
int count(const T &a) const
{
if(m2.find(a)!=m2.end()) return m2.count(a);
else if(m1.find(a)!=m1.end()) return m1.count(a);
else return 0;
}
void erase(const T &a)
{
if(m1.find(a)!=m1.end())
{
T b=m1[a];
m1.erase(a);
m2.erase(b);
}
else
{
T b=m2[a];
m2.erase(a);
m1.erase(b);
}
}
int size() const
{
return m1.size();
}
typename std::map<T,T>::const_iterator begin() const
{
return m1.begin();
}
typename std::map<T,T>::const_iterator end() const
{
return m1.end();
}
private:
std::map<T,T> m1;
std::map<T,T> m2;
};
#endif // BIMAP_H_INCLUDED
And here is the main() where i use that bidirectional map.Do not focus on 2,3,4 but only on 5 because just there I have no idea.
#include <map>
#include <functional>
#include <iostream>
#include <algorithm>
#include <string>
#include "bimap.h"
struct LengthSum
{
int length;
LengthSum():length(0) {}
void operator()(const std::pair<std::string, std::string>& p)
{
length += p.first.length();
length += p.second.length();
}
};
const int max = 1000;
int main()
{
int yourMark = 1;
// 2-es
BidirectionalMap<int> fun;
for( int i = 1; i <= max; ++i )
fun.insert( i, i + max );
BidirectionalMap<std::string> tel;
tel.insert( "Aniko", "+36(70)555-8124" );
tel.insert( "Botond", "+36(30)555-4321" );
const BidirectionalMap<std::string> ctel = tel;
if ( fun.at( 1 ) == (1 + max) &&
ctel.at( "+36(30)555-4321" ) == "Botond" )
{
yourMark = ctel.count( "Aniko" ) +
fun.count( max * 2 ) +
ctel.count( "Unknown" );
}
// 3-as
tel.erase( "+36(70)555-8124" );
if ( 0 == tel.count( "Aniko" ) &&
max == fun.size() )
{
yourMark = ctel.size() + tel.size();
}
// 4-es
const int l = std::for_each( ctel.begin(), ctel.end(), LengthSum() ).length;
yourMark = l/10;
// 5-os
std::map<double, double> md;
md[1.12] = 8.8;
md[5.4] = 7.5;
std::multimap<int, int> mmi;
mmi.insert( std::make_pair( 1, 2 ) );
mmi.insert( std::make_pair( 3, 6 ) );
mmi.insert( std::make_pair( 5, 8 ) );
//Here is the problem because i don`t know to do this :
const BidirectionalMap<int> b( mmi.begin(), mmi.end() );//??
const BidirectionalMap<double> bd( md.begin(), md.end() );//??
if ( b.at(8) == 5 )
{
yourMark = b.size() +
bd.size() +
b.count( 9 );
}
std::cout << "Your mark is " << yourMark;
std::endl( std::cout );
}
For the 2,3,4 marks i succeeded but when it comes for the best mark(5 in my country) i crashed.
So if you have the time and patience PLEASE help me :(
First of all, you are trying to copy a multimap into a map. Multimaps can have multiple items with the same index stored, while a map has only one item per index.
So, you may have to iterate over the incoming range and insert the map element wise into your maps. What you do if you have multiple indices stored in the multimap you have to decide for yourself.
Edit:
To be compatible with both map and multimap you can always make the iterator a template argument:
template<typename TIter>
BidirectionalMap(TIter beg, TIter end) {
for(TIter it = beg; it != end; ++it) {
// insert elements
}
}
I solved it like this with help from #MatthiasB
BidirectionalMap(Titer beg, Titer end)
{
for(Titer it = beg; it != end; ++it)
{
m1.insert(*it);
m2.insert(std::pair<T,T> (it->second,it->first));
}
C++11 hasn't range-based-loop for ranged integral sequence.
for(auto e : {0..10} ) // wouldn't compile!!!
So I just decided simulate it.
template< class T , bool enable = std::is_integral<T>::value >
struct range_impl
{
struct iterator
{
constexpr T operator * ()const noexcept { return value; }
iterator& operator ++()noexcept { ++value; return *this; }
friend
constexpr bool operator != (const iterator & lhs, const iterator rhs ) noexcept
{
return lhs.value != rhs.value;
}
T value;
};
constexpr iterator begin()const noexcept { return { first }; }
constexpr iterator end ()const noexcept { return { last }; }
T first;
T last ;
};
template< class T >
range_impl<T> range(T first , T last) noexcept
{
return {first, last};
}
int main(){
// print numbers in [ 0..10 ), i.e. 0 1 2 3 4 5 6 7 8 9
for(auto e : range(0,10) ) std::cout << e << ' ';
std::cout << std::endl;
}
Q: How to generalize this method for ForwardIterators?
example:
template< class ForwardIterator, class T >
bool find(ForwardIterator first, ForwardIterator last, T const& value)
{
for(auto e: range(first, last) ) if (e == v) return true;
return false;
}
Specialization
template< class Iterator>
struct range_impl<Iterator, false>
{
range_impl(Iterator first, Iterator last)
: first(first), last(last)
{}
constexpr Iterator begin()const noexcept { return { first }; }
constexpr Iterator end ()const noexcept { return { last }; }
Iterator first;
Iterator last ;
};
Test:
int main(){
for(auto e : range(0,10) ) std::cout << e << ' ';
std::cout << std::endl;
const char* a[] = { "Say", "hello", "to", "the", "world" };
for(auto e : range(a, a + 5) ) std::cout << e << ' ';
std::cout << std::endl;
}
You are trying to reimplement boost::iterator_range and boost::counting_iterator. Simply do this instead:
template< class T >
boost::iterator_range< boost::counting_iterator<T> > range( T const& tBegin, T const& tEnd ) {
return boost::iterator_range< boost::counting_iterator<T> >( tBegin, tEnd );
}
There even exists a boost::counting_range already: http://www.boost.org/doc/libs/1_47_0/libs/range/doc/html/range/reference/ranges/counting_range.html