I want to iterate over a map (pro_r) that has 3-tuples as keys. The map is an attribute of a struct called instance. When I try to initialize an iterator to the beginning of the map it gives me an error.
I tried doing the same with a locally defined map (hello) and it does not give me any error.
#include <iostream>
#include <utility> // std::pair, std::make_pair
#include <tuple> // std::pair, std::make_pair
#include <string> // std::string
#include <map>
using namespace std;
typedef tuple<int,int,int> tup3Int;
bool tup_comp (const tup3Int& lhs, const tup3Int& rhs) {
return ( get<2>(lhs) < get<2>(rhs) ) ||
((get<2>(lhs) == get<2>(rhs)) && (( get<0>(lhs) < get<0>(rhs) ))) ||
((get<2>(lhs) == get<2>(rhs)) && (( get<0>(lhs) == get<0>(rhs) )) && (( get<1>(lhs) < get<1>(rhs) ))) ;
}
struct Instance_data{
map<tup3Int,double, bool(*)(const tup3Int&,const tup3Int&)> pro_r;
};
int main ()
{
Instance_data instance;
bool(*tup_comp_ptr)(const tup3Int&,const tup3Int&) = tup_comp;
instance.pro_r = map<tup3Int,double,bool(*)(const tup3Int&,const tup3Int&)>(tup_comp_ptr);
map<tup3Int,int,bool(*)(const tup3Int&,const tup3Int&)>::const_iterator iter3 = instance.pro_r.begin();
map<tup3Int,int,bool(*)(const tup3Int&,const tup3Int&)> hello;
map<tup3Int,int,bool(*)(const tup3Int&,const tup3Int&)>::const_iterator iter2 = hello.begin();
return 0;
}
error: conversion from ‘std::map, double, bool (*)(const std::tuple&, const std::tuple&)>::iterator {aka std::_Rb_tree_iterator, double> >}’ to non-scalar type ‘std::map, int, bool (*)(const std::tuple&, const std::tuple&)>::const_iterator {aka std::_Rb_tree_const_iterator, int> >}’ requested
map::const_iterator iter3 = pro_r.begin();
Related
I am trying to sort cakeTypes vector by the size of their weight. But getting the error in sort implementation.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class CakeType
{
public:
const unsigned int weight_;
const unsigned int value_;
CakeType(unsigned int weight = 0, unsigned int value = 0) :
weight_(weight),
value_(value)
{}
};
bool compareCakes(const CakeType& cake1, const CakeType& cake2) {
return cake1.weight_ < cake2.weight_;
}
unsigned long long maxDuffelBagValue(const std::vector<CakeType>& cakeTypes,
unsigned int weightCapacity)
{
// calculate the maximum value that we can carry
unsigned cakeTypesSize = cakeTypes.size();
unsigned long long valueCalculator[weightCapacity+1][cakeTypesSize+1];
for (unsigned int i = 0; i<=weightCapacity+1; i++) {
valueCalculator[i][0] = 0;
}
for (unsigned int i = 0; i<=cakeTypesSize+1; i++) {
valueCalculator[0][i] = 0;
}
vector<CakeType> sortedCakeTypes(cakeTypes);
sort(sortedCakeTypes.begin(), sortedCakeTypes.end(), compareCakes);
return 0;
}
This is part of there error:
exited with non-zero code (1).
In file included from solution.cc:1:
In file included from /usr/include/c++/v1/iostream:38:
In file included from /usr/include/c++/v1/ios:216:
In file included from /usr/include/c++/v1/__locale:15:
In file included from /usr/include/c++/v1/string:439:
/usr/include/c++/v1/algorithm:3856:17: error: no matching function for call to 'swap'
swap(*__first, *__last);
^~~~
I tried this solution sort() - No matching function for call to 'swap', but it is not the same issue.
Data type which is used by swap function in sort algorithm must be MoveAssignable, then you can perform operation like below
CakeType c1, c2;
c1 = move(c2); // <- move c2 to c1
But in your case CakeType has const data members. You can assign values to const data members only in constructors. Code cannot be compiled because default move/copy assignment operator can't be generated by this restriction (assignment to const member is illegal).
Remove const specifier from your class definition and code will work.
class CakeType
{
public:
unsigned int weight_;
unsigned int value_;
CakeType(unsigned int weight = 0, unsigned int value = 0) :
weight_(weight),
value_(value)
{}
};
#include <cstdint>
#include <cstring>
template<typename T>
T oph_(const char *s){
constexpr std::size_t MAX = sizeof(T);
const std::size_t size = strnlen(s, MAX);
T r = 0;
for(auto it = s; it - s < size; ++it)
r = r << 8 | *it;
return r;
}
inline uint64_t oph(const char *s){
return oph_<uint64_t>(s);
}
int main(){
uint64_t const a = oph("New York City");
uint64_t const b = oph("Boston International");
return a > b;
}
I want to convert first 8 characters from const char * to uint64_t so I can easily compare if two strings are greater / lesser.
I am aware that equals will semi-work.
However I am not sure if this is most efficient implementation.
I want the implementation to work on both little and big endian machines.
This is a C implementation, that should be faster that your implementation, but I still need to use strncpy which should be the bottleneck
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <byteswap.h>
union small_str {
uint64_t v;
char buf[8];
};
static uint64_t fill_small_str(const char *str)
{
union small_str ss = { 0 };
strncpy(ss.buf, str, 8);
#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
return ss.v;
#else
return bswap_64(ss.v);
#endif
}
int main(void)
{
uint64_t const a = fill_small_str("Aew York City");
uint64_t const b = fill_small_str("Boston International");
printf("%lu ; %lu ; %d\n", a, b, (a < b));
return 0;
}
The following code doesn't compile on the latest Microsoft Visual Studio. Could someone enlighten me on what I'm doing wrong here?
#include <iostream>
#include <iomanip>
#include <array>
template <typename T, std::size_t M, std::size_t N>
using Matrix = std::array<T, M * N>;
template <typename T, std::size_t M, std::size_t N>
std::ostream &operator<<(std::ostream &os, const Matrix<T, M, N> &matrix)
{
for (auto i = 0; i < M; ++i)
{
for (auto j = 0; j < N; ++j)
{
os << std::setw(5) << matrix[i * N + j];
}
os << std::endl;
}
return os;
}
int main(int argc, const char * const argv[])
{
Matrix<float, 2, 3> matrix{
1.1f, 1.2f, 1.3f,
2.1f, 2.2f, 2.3f
};
std::cout << matrix << std::endl;
return 0;
}
Here is a snapshot of the compiler error:
1>main.cpp(30): error C2679: binary '<<': no operator found which takes a right-hand operand of type 'std::array<T,6>' (or there is no acceptable conversion)
1> with
1> [
1> T=float
1> ]
Edit:
The following code works though:
#include <iostream>
#include <iomanip>
#include <array>
template <typename T, std::size_t M, std::size_t N>
using Matrix = std::array<std::array<T, N>, M>;
template <typename T, std::size_t M, std::size_t N>
std::ostream &operator<<(std::ostream &os, const Matrix<T, M, N> &matrix)
{
for (auto row : matrix)
{
for (auto element : row)
{
os << std::setw(5) << element;
}
os << std::endl;
}
return os;
}
int main(int argc, const char * const argv[])
{
Matrix<float, 2, 3> matrix{
1.1f, 1.2f, 1.3f,
2.1f, 2.2f, 2.3f
};
std::cout << matrix << std::endl;
return 0;
}
Bearing in mind #dyp's comment what you have to do here is to create the new type instead of alias that will have 2 independent params.
So you just use aggregation including actual data as a field, like:
template <typename T, std::size_t M, std::size_t N>
class Matrix
{
private:
std::array<T, M * N> _data;
template <typename T1, std::size_t M1, std::size_t N1> friend std::ostream &operator<<(std::ostream &os, const Matrix<T1, M1, N1> &matrix);
public:
template <typename...Args>
Matrix(Args... args):
_data{{std::forward<Args>(args)...}}
{}
};
Call to the extract function below does not work for me on g++ 4.9.0 (20130421). The error I get is that s1 is not a constant expression. If i can be initialized as constexpr then j and k should too. Is that wrong?
#include <tuple>
template <unsigned N1, unsigned N2>
constexpr bool strmatch(const char (&s1)[N1], const char (&s2)[N2], unsigned i = 0)
{
return (s1[i]==s2[i]) ?
(s1[i]=='\0') ?
true
: strmatch(s1, s2, i+1)
: false;
}
template<unsigned N>
constexpr int extract(const std::tuple<int, int> & t1, const char (&array)[N]) {
return std::get<strmatch(array, "m0")>(t1);
}
int main(void)
{
constexpr int i = strmatch("m0", "m0"); // OK
constexpr int j = extract(std::make_tuple(10, 20), "m0");
constexpr int k = extract(std::make_tuple(10, 20), "m1");
return 0;
}
Your code is ill-formed. The problem is that array is not a core constant expression, so can't be used in the template argument in the call to std::get:
template<unsigned N>
constexpr int extract(const std::tuple<int, int> & t1, const char (&array)[N]) {
return std::get<strmatch(array, "m0")>(t1);
}
Remember that constexpr functions can be called at runtime: this code would use the value of a runtime parameter to this function (array) during translation (in the evaluation of the call to strmatch).
I need to find an element of vector which is presented in map. Hard part is that vector consists of structures, so you should call member function to extract value form the structure first to compare it to the map elements.
So, with for cycle it's pretty easy:
vector<A>::iterator it;
for( it = vec.begin(); it != vec.end(); ++it )
{
if( mp.count( it->getKey() ) )
{
break;
}
}
My question: is there any way to do it in one line, something like
//this doesn't work as count accepts key_type
vector<A>::iterator it = find_if( vec.begin(), vec.end(), boost::bind( &map<string, string>::count, mp, boost::bind( &A::getKey, _1 ) )) != 0);
Full example, to test
#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
#include <boost/bind.hpp>
#include <boost/assign.hpp>
using namespace std;
class A{
public:
A( const std::string& key )
: key( key ) {}
std::string getKey(){ return key; }
private:
std::string key;
};
int main(int argc, const char *argv[]) {
map<string, string> mp = boost::assign::map_list_of( "Key1", "Val1" ) ( "Key2", "Val2" ) ( "Key3", "Val3" );
vector<A> vec = boost::assign::list_of( "AAA" ) ( "Key2" ) ( "BBB" );
// vector<A>::iterator it = find_if( vec.begin(), vec.end(), boost::bind( &map<string, string>::count, mp, boost::bind( &A::getKey, _1 ) )) != 0);
vector<A>::iterator it;
for( it = vec.begin(); it != vec.end(); ++it )
{
if( mp.count( it->getKey() ) )
{
break;
}
}
cout << ( it != vec.end() ? "found" : "not found" ) << endl;
return 0;
}
Thanks in advance
Your solution was close, there is just one closing parenthesis too many. Placing each parenthesis on a newline with indenting for each level emphasizes the invalid parenthesis:
vector<A>::iterator it = find_if
(
vec.begin(), vec.end(), boost::bind
(
&map<string, string>::count, &mp, boost::bind
(
&A::getKey, _1
)
)
) // one too many
!= 0);
In its simplest form, the line becomes iterator = find_if(...) != 0), which will cause the compiler to fail on either:
Not being able to find operator!=(iterator, int).
The ) token in != 0).
With correct parentheses, != 0 uses an operator overload provided by boost::bind. The line would look like:
vector<A>::iterator it = find_if(vec.begin(), vec.end(),
boost::bind(&map<string, string>::count, &mp,
boost::bind(&A::getKey, _1)) != 0);
However, consider the readability of such a simple operation. If a simple for loop is not generic and reusable enough, then consider hiding it within a convenience function:
template <typename InputIterator,
typename C,
typename Fn>
InputIterator find_if_contains(
InputIterator first,
InputIterator last,
const C& container,
Fn fn)
{
while (first != last)
{
if (0 != container.count(fn(*first))) return first;
++first;
}
return last;
}
...
vector<A>::iterator it = find_if_contains(
vec.begin(), vec.end(),
mp, boost::bind(&A::getKey, _1)
);
Otherwise, a custom predicate type may enhance readability while providing some extra flexibility for reuse with different types. For example, consider the following predicate type that works for various types of associative containers:
template <typename C,
typename Fn>
struct contains_predicate
{
contains_predicate(const C& container, Fn fn)
: container_(&container), fn_(fn)
{}
template <typename T>
bool operator()(T& t)
{
return 0 != container_->count(fn_(t));
}
const C* container_;
Fn fn_;
};
template <typename C,
typename Fn>
contains_predicate<C, Fn>
contains(const C& container, Fn fn)
{
return contains_predicate<C, Fn>(container, fn);
}
...
vector<A>::iterator it = find_if(vec.begin(), vec.end(),
contains(mp, boost::bind(&A::getKey, _1)));
In C++11, use a lambda:
find_if(vec.begin(), vec.end(), [&](A const & a){return mp.count(a.getKey());});
But since you're using Boost.Assign rather than uniform initialisation, perhaps you can't do that. I'm afraid I don't know how to construct a functor like that using bind alone.