C++ comparing bunch of values with a given one - c++

I need to compare one given value with a retrieved values. I do this several times in the code. I am not satisfied with how it looks and I am seeking for a some sort of an util function. Anyone wrote one?
Number of values I am comparing with is known at the compile time.
Update: I'd like to get rid of containers as I know exact amount of values ( often not more then 3 ) I want to compare with. And it is not so convenient to put items to the container every time.
I don't love if neither because it is not obvious as "find".
#include <algorithm>
#include <string>
#include <vector>
std::string getValue1()
{
return "test";
}
std::string getValue2()
{
return "the";
}
std::string getValue3()
{
return "world";
}
int main()
{
const std::string value = "the";
// simple if
if ( value == getValue1() ||
value == getValue2() ||
value == getValue3() )
return 1;
// using collections like vector, set
std::vector<std::string> values;
values.push_back( getValue1() );
values.push_back( getValue2() );
values.push_back( getValue3() );
if ( values.end() != std::find( values.begin(), values.end(), value ) )
return 1;
// third option I'd use instead
//
return 0;
}

If the values you're looking for are Comparable with operator< (like ints, float and std::strings), then it's faster to use an std::set to put the values there and then check set.find(value) == set.end(). This is because the set will store the values with a certain order that allows for faster lookups. Using an hash table will be even faster. However, for less than 50 values or so you might not notice any difference :) So my rule of thumb would be:
Less then 5 items: if with multiple ||
5 or more: put in a set or hash table

you can write a set of template functions which will help you through with this, for example:
template <typename T>
bool InSet(const T & item, const T & i1, const T & i2) {
return item==i1 || item==i2;
}
template <typename T>
bool InSet(const T & item, const T & i1, const T & i2, const T & i3) {
return item==i1 || item==i2 || item==i3;
}
Note that you can make InSet to work like it took a variable number of arguments by creating multiple templates with different number of arguments.
And then:
int i;
if (InSet(i, 3, 4, 5)) { ... }
string s;
if (InSet(s, "foobar", "zap", "garblex")) { ... }
etc.

For your request to do
if (InSet(value)(GetValue1(), GetValue2(), GetValue3()))
{
// Do something here...
}
Try this:
template <typename T>
class InSetHelper
{
const T &Value;
void operator=(const InSetHelper &);
public:
InSetHelper(const T &value) : Value(value) {}
template<class Other, class Another>
bool operator()(const Other &value1, const Another &value2) const
{
return Value == value1 || Value == value2;
}
template<class Other, class Another, class AThird>
bool operator()(const Other &value1, const Another &value2, const AThird &value3) const
{
return Value == value1 || Value == value2 || Value == value3;
}
};
template <typename T>
InSetHelper<T> InSet(const T &value) { return InSetHelper<T>(value); }
This syntax might be more clear though:
if (MakeSet(GetValue1(), GetValue2(), GetValue3()).Contains(value))
{
// Do something here...
}
template <typename T, typename U, typename V>
class Set3
{
const T& V1;
const U& V2;
const V& V3;
void operator=(const Set3 &);
public:
Set3(const T &v1, const U &v2, const V &v3) : V1(v1), V2(v2), V3(v3) {}
template <typename W>
bool Contains(const W &v) const
{
return V1 == v || V2 == v || V3 == v;
}
};
template <typename T, typename U>
class Set2
{
// as above
};
template <typename T, typename U, typename V>
Set3<T, U, V> MakeSet(const T &v1, const U &v2, const V &v3)
{
return Set3<T, U, V>(v1, v2, v3);
}
template <typename T, typename U>
Set3<T, U> MakeSet(const T &v1, const U &v23)
{
return Set3<T, U, V>(v1, v2);
}
If those values are really part of a tree or a linked list, then you have your set/container already, and your best bet is to just use some recursion:
parent.ThisOrDescendantHasValue(value);
You'd just add this to whatever class parent and child belong to:
class Node
{
public:
Value GetValue();
Node *GetChild();
bool ThisOrDescendantHasValue(const Value &value)
{
return GetValue() == value
|| (GetChild() && GetChild->ThisOrDescendantHasValue(value));
}
};

You don't need a std::set or a std::vector. Just use std::set_intersection()...
Code is best...
#include <set>
#include <iostream>
#include <iterator>
using namespace std;
#define COUNT(TYPE,ARRAY) ( sizeof(ARRAY) / sizeof(TYPE) )
inline bool CaseInsensitiveCompare (const char * a, const char * b)
{ return strcasecmp( a, b ) < 0; }
int main()
{
const char * setA[] = { "the", "world", "is", "flat" };
const char * setB[] = { "the", "empty", "set", "is", "boring" };
stable_sort( setA, setA + COUNT( const char *, setA ),
CaseInsensitiveCompare );
stable_sort( setB, setB + COUNT( const char *, setB ),
CaseInsensitiveCompare );
cout << "Intersection of sets: ";
set_intersection( setA, setA + COUNT( const char *, setA ),
setB, setB + COUNT( const char *, setB ),
ostream_iterator<const char *>(cout, " "),
CaseInsensitiveCompare );
cout << endl << endl;
}
Or perhaps, given your 1-N lookup problem:
(Note: Use binary_search() AFTER sorting!)
if ( binary_search( setA, setA + COUNT( const char *, setA ),
"is", CaseInsensitiveCompare ) )
...
if ( binary_search( setA, setA + COUNT( const char *, setA ),
"set", CaseInsensitiveCompare ) )
...

Which changes more, the 'value' or the values returned by 'getValueX()'? You can insert everything into a hash_map/map and then do a search that way, as you've suggested with the containers.

std::find_first_of.
Of course, if you only care about finding a single value, you can create your own wrapper around std::find.

I would recommend your method 2, using a std::vector or other container and looking for membership. Since the order of elements that you're checking against is probably not relevant, you may want to use a std::set or std::map. If you have very many items in your set of values, then using a set or a map will be a faster, while if you have only a few a vector may be faster.
The advantage of any of these approaches is that you can then store the set/map somewhere common, and avoid having to build the set of matching responses every time.

i like the collections approach, maybe use a hash_set instead of a vector. store the values in a property file and have a method to populat the hash_set from the file, and another one to return a boolean if the value is in the hash_set. then you can get down to one 2 lines in the main code.

It depends on the source of the retrieved values, if you're reading in from a file or stream then you'd do something different but if your source is a series of functions then the following is a different way to do it, not perfect but may suit your needs:
const int count = 3;
std::string value = "world";
boost::function<std::string(void)> funcArray[count];
funcArray[0] = &getValue1;
funcArray[1] = &getValue2;
funcArray[2] = &getValue3;
for( int i = 0; i < count; ++i )
{
if( funcArray[i]() == value )
return 1;
}
If you know which functions are the source (as well as the count of objects) I expect you could assemble the function pointer array using the preprocessor.

How about using a boost::array (or std::tr1::array) and creating a simple function like this:
template <typename ValueType, size_t arraySize>
bool contains(const boost::array<ValueType, arraySize>& arr, const ValueType& val)
{
return std::find(arr.begin(), arr.end(), val)!=arr.end();
}
You could then reuse that pretty easily:
#include <string>
#include <iostream>
#include <boost\array.hpp>
template <typename ValueType, size_t arraySize>
bool contains(const boost::array<ValueType, arraySize>& arr, const ValueType& val)
{
return std::find(arr.begin(), arr.end(), val)!=arr.end();
}
int _tmain(int argc, _TCHAR* argv[])
{
boost::array<std::string, 3> arr = {"HI", "there", "world"};
std::cout << std::boolalpha
<< "arr contains HI: " << contains(arr, std::string("HI")) << std::endl
<< "arr contains blag: " << contains(arr, std::string("blag") ) << std::endl
<< "arr contains there: " << contains(arr, std::string("there") ) << std::endl;
return 0;
}
Edit: So boost is out. It's pretty easy to adapt this to a regular array:
template <typename ValueType, size_t arraySize>
bool contains(ValueType (&arr)[arraySize], const ValueType& val)
{
return std::find(&arr[0], &arr[arraySize], val)!=&arr[arraySize];
}
int _tmain(int argc, _TCHAR* argv[])
{
std::string arr[3] = {"HI", "there", "world"};
std::cout << std::boolalpha << "arr contains HI: " << contains(arr, std::string("HI")) << std::endl
<< "arr contains blag: " << contains(arr, std::string("blag") ) << std::endl
<< "arr contains there: " << contains(arr, std::string("there") ) << std::endl;
return 0;
}

Related

std::num_put issue with nan-boxing due to auto-cast from float to double

I'm using this post to extend nan values with some extra info and this post to modify std::cout behaviour and display this extra info.
Here is the code defining the functions and NumPut class:
#include <iostream>
#include <assert.h>
#include <limits>
#include <bitset>
#include <cmath>
#include <locale>
#include <ostream>
#include <sstream>
template <typename T>
void showValue( T val, const std::string& what )
{
union uT {
T d;
unsigned long long u;
};
uT ud;
ud.d = val;
std::bitset<sizeof(T) * 8> b(ud.u);
std::cout << val << " (" << what << "): " << b.to_string() << std::endl;
}
template <typename T>
T customizeNaN( T value, char mask )
{
T res = value;
char* ptr = (char*) &res;
assert( ptr[0] == 0 );
ptr[0] |= mask;
return res;
}
template <typename T>
bool isCustomNaN( T value, char mask )
{
char* ptr = (char*) &value;
return ptr[0] == mask;
}
template <typename T>
char getCustomNaNMask( T value )
{
char* ptr = (char*) &value;
return ptr[0];
}
template <typename Iterator = std::ostreambuf_iterator<char> >
class NumPut : public std::num_put<char, Iterator>
{
private:
using base_type = std::num_put<char, Iterator>;
public:
using char_type = typename base_type::char_type;
using iter_type = typename base_type::iter_type;
NumPut(std::size_t refs = 0)
: base_type(refs)
{}
protected:
virtual iter_type do_put(iter_type out, std::ios_base& str, char_type fill, double v) const override {
if(std::isnan(v))
{
char mask = getCustomNaNMask(v);
if ( mask == 0x00 )
{
out = std::copy(std::begin(NotANumber), std::end(NotANumber), out);
}
else
{
std::stringstream maskStr;
maskStr << "(0x" << std::hex << (unsigned) mask << ")";
std::string temp = maskStr.str();
out = std::copy(std::begin(CustomNotANumber), std::end(CustomNotANumber), out);
out = std::copy(std::begin(temp), std::end(temp), out);
}
}
else
{
out = base_type::do_put(out, str, fill, v);
}
return out;
}
private:
static const std::string NotANumber;
static const std::string CustomNotANumber;
};
template<typename Iterator> const std::string NumPut<Iterator>::NotANumber = "Not a Number";
template<typename Iterator> const std::string NumPut<Iterator>::CustomNotANumber = "Custom Not a Number";
inline void fixNaNToStream( std::ostream& str )
{
str.imbue( std::locale(str.getloc(), new NumPut<std::ostreambuf_iterator<char>>() ) );
}
A simple test function:
template<typename T>
void doTest()
{
T regular_nan = std::numeric_limits<T>::quiet_NaN();
T myNaN1 = customizeNaN( regular_nan, 0x01 );
T myNaN2 = customizeNaN( regular_nan, 0x02 );
showValue( regular_nan, "regular" );
showValue( myNaN1, "custom 1" );
showValue( myNaN2, "custom 2" );
}
My main program:
int main(int argc, char *argv[])
{
fixNaNToStream( std::cout );
doTest<double>();
doTest<float>();
return 0;
}
doTest<double> outputs:
Not a Number (regular): 0111111111111000000000000000000000000000000000000000000000000000
Custom Not a Number(0x1) (custom 1): 0111111111111000000000000000000000000000000000000000000000000001
Custom Not a Number(0x2) (custom 2): 0111111111111000000000000000000000000000000000000000000000000010
doTest<float> outputs:
Not a Number (regular): 01111111110000000000000000000000
Not a Number (custom 1): 01111111110000000000000000000001
Not a Number (custom 2): 01111111110000000000000000000010
While I would expect for float:
Not a Number (regular): 01111111110000000000000000000000
Custom Not a Number(0x1) (custom 1): 01111111110000000000000000000001
Custom Not a Number(0x2) (custom 2): 01111111110000000000000000000010
The problem is that num_put only has a virtual do_put for double, not for float. So my float is silently casted to a double, losing my extended information.
I know there are some alternatives, like using FloatFormat from the second post, or simply writing a smart float2double function and calling it prior to sending my NaN value to the output stream, but they require the developer to take care of this situation...and he may forget to.
Is there no way to implement that within NumPut class or anything else that would simply make things work when a float is send to the imbued stream as nicely as it works for a double?
My requirement is to be able to simply call a function like fixNaNToStream for any output stream (std::cout, local std::stringstream, ...) and then send float and double to it and get them identified as my custom NaNs and displayed accordingly.
The problem is that num_put only has a virtual do_put for double, not for float. So my float is silently casted to a double, losing my extended information.
The information is lost because the positions of the bits carrying it are different when the number is converted from float to double:
// Assuming an IEE-754 floating-point representation of float and double
0 11111111 10000000000000000000010
0 11111111111 1000000000000000000001000000000000000000000000000000
Note that the mantissa bits are "shifted" by 3 positions, because the exponent requires 3 more bits.
Also, it's worth noting what it's stated in this page: https://en.cppreference.com/w/cpp/numeric/math/isnan
Copying a NaN is not required, by IEEE-754, to preserve its bit representation (sign and payload), though most implementation do.
I assume the same holds for casting such values, so that, even ignoring other causes of undefined behavior in OP's code, whether a method of NaN-boxing could work or not is actually implementation defined.
In my former attempts of answering this question, I used some explicit bit shifting by different offset to achive the result, but as jpo38 also found out, the easiest way is to always generate a float NaN and then cast correctly.
The Standard Library function std::nanf could be used to generate a "customized" float NaN, but in the following demo snippet I won't use it.
#include <cstdint>
#include <limits>
#include <cstring>
#include <cassert>
#include <type_traits>
#include <iostream>
#include <bitset>
#include <array>
#include <climits>
namespace my {
// Waiting for C++20 std::bit_cast
// source: https://en.cppreference.com/w/cpp/numeric/bit_cast
template <class To, class From>
typename std::enable_if<
(sizeof(To) == sizeof(From)) &&
std::is_trivially_copyable<From>::value &&
std::is_trivial<To>::value,
// this implementation requires that To is trivially default constructible
To>::type
// constexpr support needs compiler magic
bit_cast(const From &src) noexcept
{
To dst;
std::memcpy(&dst, &src, sizeof(To));
return dst;
}
template <typename T, std::size_t Size = sizeof(T)>
void print_bits(T x)
{
std::array<unsigned char, Size> buf;
std::memcpy(buf.data(), &x, Size);
for (auto it = buf.crbegin(); it != buf.crend(); ++it)
{
std::bitset<CHAR_BIT> b{*it};
std::cout << b.to_string();
}
std::cout << '\n';
}
// The following assumes that both floats and doubles store the mantissa
// in the lower bits and that while casting a NaN (float->double or double->float)
// the most significant of those aren't changed
template <typename T>
auto boxed_nan(uint8_t data = 0) -> typename std::enable_if<std::numeric_limits<T>::has_quiet_NaN, T>::type
{
return bit_cast<float>(
bit_cast<uint32_t>(std::numeric_limits<float>::quiet_NaN()) |
static_cast<uint32_t>(data)
);
}
template <typename T>
uint8_t unbox_nan(T num)
{
return bit_cast<uint32_t>(static_cast<float>(num));
}
}; // End of namespace 'my'
int main()
{
auto my_nan = my::boxed_nan<float>(42);
my::print_bits(my_nan);
my::print_bits(static_cast<double>(my_nan));
assert(my::unbox_nan(my_nan) == 42);
assert(my::unbox_nan(static_cast<double>(my_nan)) == 42);
auto my_d_nan = my::boxed_nan<double>(17);
my::print_bits(my_d_nan);
my::print_bits(static_cast<float>(my_d_nan));
assert(my::unbox_nan(my_d_nan) == 17);
assert(my::unbox_nan(static_cast<float>(my_d_nan)) == 17);
auto my_ld_nan = my::boxed_nan<long double>(9);
assert(my::unbox_nan(my_ld_nan) == 9);
assert(my::unbox_nan(static_cast<double>(my_ld_nan)) == 9);
}
As Bob pointed, the double extended bit should be at the same relative position to biased exponent than it is for float if you want cast to work in both ways (from float to double and from double to float).
Considering that, a very trivial approach to handle that is to use the far right bit for the float. For for double, instead of trying to determine manually what bit should be used, simply douse cast operations and let the system identify where is the right place...
Then code becomes:
#include <iostream>
#include <assert.h>
#include <limits>
#include <bitset>
#include <cmath>
#include <locale>
#include <ostream>
#include <sstream>
template <typename T>
void showValue( T val, const std::string& what )
{
union uT {
T d;
unsigned long long u;
};
uT ud;
ud.d = val;
std::bitset<sizeof(T) * 8> b(ud.u);
std::cout << val << " (" << what << "): " << b.to_string() << std::endl;
}
char& getCustomNaNMask( float& value )
{
char* ptr = (char*) &value;
return ptr[0];
}
/** temp parameter is mainly used because we can't have two functions with same prototype even if they return different values */
float getCustomizedNaN( char mask, float temp )
{
// let's reuse temp argument as we need a local float variable
temp = std::numeric_limits<float>::quiet_NaN();
getCustomNaNMask(temp) |= mask;
return temp;
}
/** temp parameter is mainly used because we can't have two functions with same prototype even if they return different values */
double getCustomizedNaN( char mask, double temp )
{
float asFloat = getCustomizedNaN( mask, float() );
// Let the system correctly cast from float to double, that's it!
return static_cast<double>( asFloat );
}
template <typename T>
bool isCustomNaN( T value, char mask )
{
return getCustomNaNMask(value) == mask;
}
template <typename Iterator = std::ostreambuf_iterator<char> >
class NumPut : public std::num_put<char, Iterator>
{
private:
using base_type = std::num_put<char, Iterator>;
public:
using char_type = typename base_type::char_type;
using iter_type = typename base_type::iter_type;
NumPut(std::size_t refs = 0)
: base_type(refs)
{}
protected:
virtual iter_type do_put(iter_type out, std::ios_base& str, char_type fill, double v) const override {
if(std::isnan(v))
{
float asFloat = static_cast<float>( v );
char& mask = getCustomNaNMask(asFloat);
if ( mask == 0x00 )
{
out = std::copy(std::begin(NotANumber), std::end(NotANumber), out);
}
else
{
std::stringstream maskStr;
maskStr << "(0x" << std::hex << (unsigned) mask << ")";
std::string temp = maskStr.str();
out = std::copy(std::begin(CustomNotANumber), std::end(CustomNotANumber), out);
out = std::copy(std::begin(temp), std::end(temp), out);
}
}
else
{
out = base_type::do_put(out, str, fill, v);
}
return out;
}
private:
static const std::string NotANumber;
static const std::string CustomNotANumber;
};
template<typename Iterator> const std::string NumPut<Iterator>::NotANumber = "Not a Number";
template<typename Iterator> const std::string NumPut<Iterator>::CustomNotANumber = "Custom Not a Number";
inline void fixNaNToStream( std::ostream& str )
{
str.imbue( std::locale(str.getloc(), new NumPut<std::ostreambuf_iterator<char>>() ) );
}
And test program:
template<typename T>
void doTest()
{
T regular_nan = std::numeric_limits<T>::quiet_NaN();
T myNaN1 = getCustomizedNaN( 0x01, T() );
T myNaN2 = getCustomizedNaN( 0x02, T() );
showValue( regular_nan, "regular" );
showValue( myNaN1, "custom 1" );
showValue( myNaN2, "custom 2" );
}
int main(int argc, char *argv[])
{
fixNaNToStream( std::cout );
doTest<double>();
doTest<float>();
return 0;
}
Outputs:
Not a Number (regular): 0111111111111000000000000000000000000000000000000000000000000000
Custom Not a Number(0x1) (custom 1): 0111111111111000000000000000000000100000000000000000000000000000
Custom Not a Number(0x2) (custom 2): 0111111111111000000000000000000001000000000000000000000000000000
Not a Number (regular): 01111111110000000000000000000000
Custom Not a Number(0x1) (custom 1): 01111111110000000000000000000001
Custom Not a Number(0x2) (custom 2): 01111111110000000000000000000010
Thanks Bob!

How to find indexes of the n greatest elements

I have a container (Vector) of some arbitrary type and i want to get a vector with indices of the n greatest (or smallest) elements.
Is there a standard way to do so?
This is exactly the topic of one of the guru of the week http://www.gotw.ca/gotw/073.htm
I am reporting the preferred solution, however, I strongly recommend you to read the article (and the blog in general), it is really good.
#include <vector>
#include <map>
#include <algorithm>
namespace Solution3
{
template<class T>
struct CompareDeref
{
bool operator()( const T& a, const T& b ) const
{ return *a < *b; }
};
template<class T, class U>
struct Pair2nd
{
const U& operator()( const std::pair<T,U>& a ) const
{ return a.second; }
};
template<class IterIn, class IterOut>
void sort_idxtbl( IterIn first, IterIn last, IterOut out )
{
std::multimap<IterIn, int, CompareDeref<IterIn> > v;
for( int i=0; first != last; ++i, ++first )
v.insert( std::make_pair( first, i ) );
std::transform( v.begin(), v.end(), out,
Pair2nd<IterIn const,int>() );
}
}
#include <iostream>
int main()
{
int ai[10] = { 15,12,13,14,18,11,10,17,16,19 };
std::cout << "#################" << std::endl;
std::vector<int> aidxtbl( 10 );
// use another namespace name to test a different solution
Solution3::sort_idxtbl( ai, ai+10, aidxtbl.begin() );
for( int i=0; i<10; ++i )
std::cout << "i=" << i
<< ", aidxtbl[i]=" << aidxtbl[i]
<< ", ai[aidxtbl[i]]=" << ai[aidxtbl[i]]
<< std::endl;
std::cout << "#################" << std::endl;
}

C++11 for each loop with more than one variable

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 cannot make a copy constructor for a bidirectional map

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));
}

Slicing std::array

Is there an easy way to get a slice of an array in C++?
I.e., I've got
array<double, 10> arr10;
and want to get array consisting of five first elements of arr10:
array<double, 5> arr5 = arr10.???
(other than populating it by iterating through first array)
The constructors for std::array are implicitly defined so you can't initialize it with a another container or a range from iterators. The closest you can get is to create a helper function that takes care of the copying during construction. This allows for single phase initialization which is what I believe you're trying to achieve.
template<class X, class Y>
X CopyArray(const Y& src, const size_t size)
{
X dst;
std::copy(src.begin(), src.begin() + size, dst.begin());
return dst;
}
std::array<int, 5> arr5 = CopyArray<decltype(arr5)>(arr10, 5);
You can also use something like std::copy or iterate through the copy yourself.
std::copy(arr10.begin(), arr10.begin() + 5, arr5.begin());
Sure. Wrote this:
template<int...> struct seq {};
template<typename seq> struct seq_len;
template<int s0,int...s>
struct seq_len<seq<s0,s...>>:
std::integral_constant<std::size_t,seq_len<seq<s...>>::value> {};
template<>
struct seq_len<seq<>>:std::integral_constant<std::size_t,0> {};
template<int Min, int Max, int... s>
struct make_seq: make_seq<Min, Max-1, Max-1, s...> {};
template<int Min, int... s>
struct make_seq<Min, Min, s...> {
typedef seq<s...> type;
};
template<int Max, int Min=0>
using MakeSeq = typename make_seq<Min,Max>::type;
template<std::size_t src, typename T, int... indexes>
std::array<T, sizeof...(indexes)> get_elements( seq<indexes...>, std::array<T, src > const& inp ) {
return { inp[indexes]... };
}
template<int len, typename T, std::size_t src>
auto first_elements( std::array<T, src > const& inp )
-> decltype( get_elements( MakeSeq<len>{}, inp ) )
{
return get_elements( MakeSeq<len>{}, inp );
}
Where the compile time indexes... does the remapping, and MakeSeq makes a seq from 0 to n-1.
Live example.
This supports both an arbitrary set of indexes (via get_elements) and the first n (via first_elements).
Use:
std::array< int, 10 > arr = {0,1,2,3,4,5,6,7,8,9};
std::array< int, 6 > slice = get_elements(arr, seq<2,0,7,3,1,0>() );
std::array< int, 5 > start = first_elements<5>(arr);
which avoids all loops, either explicit or implicit.
2018 update, if all you need is first_elements:
Less boilerplaty solution using C++14 (building up on Yakk's pre-14 answer and stealing from "unpacking" a tuple to call a matching function pointer)
template < std::size_t src, typename T, int... I >
std::array< T, sizeof...(I) > get_elements(std::index_sequence< I... >, std::array< T, src > const& inp)
{
return { inp[I]... };
}
template < int N, typename T, std::size_t src >
auto first_elements(std::array<T, src > const& inp)
-> decltype(get_elements(std::make_index_sequence<N>{}, inp))
{
return get_elements(std::make_index_sequence<N>{}, inp);
}
Still cannot explain why this works, but it does (for me on Visual Studio 2017).
This answer might be late... but I was just toying around with slices - so here is my little home brew of std::array slices.
Of course, this comes with a few restrictions and is not ultimately general:
The source array from which a slice is taken must not go out of scope. We store a reference to the source.
I was looking for constant array slices first and did not try to expand this code to both const and non const slices.
But one nice feature of the code below is, that you can take slices of slices...
// ParCompDevConsole.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include "pch.h"
#include <cstdint>
#include <iostream>
#include <array>
#include <stdexcept>
#include <sstream>
#include <functional>
template <class A>
class ArraySliceC
{
public:
using Array_t = A;
using value_type = typename A::value_type;
using const_iterator = typename A::const_iterator;
ArraySliceC(const Array_t & source, size_t ifirst, size_t length)
: m_ifirst{ ifirst }
, m_length{ length }
, m_source{ source }
{
if (source.size() < (ifirst + length))
{
std::ostringstream os;
os << "ArraySliceC::ArraySliceC(<source>,"
<< ifirst << "," << length
<< "): out of bounds. (ifirst + length >= <source>.size())";
throw std::invalid_argument( os.str() );
}
}
size_t size() const
{
return m_length;
}
const value_type& at( size_t index ) const
{
return m_source.at( m_ifirst + index );
}
const value_type& operator[]( size_t index ) const
{
return m_source[m_ifirst + index];
}
const_iterator cbegin() const
{
return m_source.cbegin() + m_ifirst;
}
const_iterator cend() const
{
return m_source.cbegin() + m_ifirst + m_length;
}
private:
size_t m_ifirst;
size_t m_length;
const Array_t& m_source;
};
template <class T, size_t SZ>
std::ostream& operator<<( std::ostream& os, const std::array<T,SZ>& arr )
{
if (arr.size() == 0)
{
os << "[||]";
}
else
{
os << "[| " << arr.at( 0 );
for (auto it = arr.cbegin() + 1; it != arr.cend(); it++)
{
os << "," << (*it);
}
os << " |]";
}
return os;
}
template<class A>
std::ostream& operator<<( std::ostream& os, const ArraySliceC<A> & slice )
{
if (slice.size() == 0)
{
os << "^[||]";
}
else
{
os << "^[| " << slice.at( 0 );
for (auto it = slice.cbegin() + 1; it != slice.cend(); it++)
{
os << "," << (*it);
}
os << " |]";
}
return os;
}
template<class A>
A unfoldArray( std::function< typename A::value_type( size_t )> producer )
{
A result;
for (size_t i = 0; i < result.size(); i++)
{
result[i] = producer( i );
}
return result;
}
int main()
{
using A = std::array<float, 10>;
auto idf = []( size_t i ) -> float { return static_cast<float>(i); };
const auto values = unfoldArray<A>(idf);
std::cout << "values = " << values << std::endl;
// zero copy slice of values array.
auto sl0 = ArraySliceC( values, 2, 4 );
std::cout << "sl0 = " << sl0 << std::endl;
// zero copy slice of the sl0 (the slice of values array)
auto sl01 = ArraySliceC( sl0, 1, 2 );
std::cout << "sl01 = " << sl01 << std::endl;
return 0;
}