I have an array std::vector<int> and an enum class Foo : int. Is there a better way to cast or convert than a reinterpret_cast?
std::vector<int> v;
auto& c = *reinterpret_cast<std::vector<Foo>*>(&v);
https://godbolt.org/z/M6ofkF
Combine a static_cast with std::transform.
#include <algorithm>
#include <vector>
#include <cassert>
enum class Foo : int {
A = 0,
B = 1,
C = 2,
D = 3,
E = 4,
F = 5
};
std::vector<Foo> convert(std::vector<int> const &in) {
std::vector<Foo> out;
out.reserve(in.size());
std::transform(in.begin(), in.end(), std::back_inserter(out),
[](int n) { return static_cast<Foo>(n); });
return out;
}
int main() {
std::vector<int> vec{1, 2, 3, 4, 5};
std::vector<Foo> c = convert(vec);
assert(c[3] == Foo::E);
return 0;
}
Reference: How to cast int to enum in C++?
Related
#include <algorithm>
#include <array>
#include <iostream>
int main() {
std::array<int, 10> s{5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
struct {
bool operator()(int a, int b) const
{
return a < b;
}
} customLess;
std::sort(s.begin(), s.end(), customLess);
for (auto a : s) {
std::cout << a << " ";
}
std::cout << '\n';
return 0;
}
I want to sort the array using std : : sort. The code above works fine, but when I try with template array in my main task (GArr<int, 5> arr{5, 2, 3, 4, 1};) the compiler gives the following
error: no match for 'operator-' (operand types are 'Iterator' and
'Iterator')|
How can I fix it?
Is there a standard algorithm that I can use to subset a vector of structs by a vector of pointers to these structs?
E.g.
typedef struct {
int a;
char b;
} some_struct_t;
int main()
{
std::vector<some_struct_t> v = { {10, '1'}, { 5, '2'} };
std::vector<some_struct_t*> v2;
std::some_subset_command<some_struct_t, some_struct_t*>(begin(v), end(v), std::back_inserter(v2), [](const somestruct&) { if (somestruct.a == 5) { return &somestruct; }});
}
some_subset_command() should construct the new vector using the back_inserter and the output from the lambda predicate.
How can I do this in the most declarative way?
If you don't mind changing your std::vector<some_struct_t*> v2 to a std::vector<std::reference_wrapper<some_struct_t>> v2 (include <functional>), you could use std::copy_if:
#include <vector>
#include <algorithm>
#include <functional>
typedef struct {
int a;
char b;
} some_struct_t;
int main()
{
std::vector<some_struct_t> v = { {10, '1'}, { 5, '2'} };
std::vector<std::reference_wrapper<some_struct_t>> v2;
std::copy_if(begin(v), end(v), std::back_inserter(v2), [](const auto &s) {
return s.a == 5;
});
}
More information for std::reference_wrapper at cppreference.
If your compiler supports C++20, then you can use range adaptors:
#include <ranges>
#include <vector>
typedef struct {
int a;
char b;
} some_struct_t;
int main()
{
std::vector<some_struct_t> v = { {10, '1'}, { 5, '2'} };
auto r = v | std::views::filter([](auto& somestruct) { return somestruct.a == 5; })
| std::views::transform([](auto& somestruct) { return &somestruct; });
std::vector<some_struct_t*> v2(r.begin(), r.end());
}
Demo.
What can be wrong this piece of code.
I'm trying to call countLessThan3 by instantiating with std::vector.
// 3. Lambdas
template<typename T>
const auto countLessThan3(const T & vec, int value)
{
const auto count = std::count(vec.begin(), vec.end(),
[](int i){ return i < 3;}
);
return count;
}
int main(int argc, char const *argv[])
{
// 3
std::vector<int> vector = {1, 2, 3, 4, 5, 2, 2, 2};
countLessThan3<std::vector<int>>(vector, 3);
return 0;
}
compiled with g++ -std=c++14 1.cpp -o 1 on linux.
Ther are some problems:
The code uses std::count, but a lambda is passed, so it should be std::count_if instead.
value is passed to the function as a parameter, but it is not used and there is an hard coded 3 in the lambda.
Other minor issues are fixed in the snippet below
#include <iostream>
#include <vector>
#include <algorithm>
template<typename T>
auto countLessThan(const T & vec, typename T::value_type value)
{
return std::count_if(vec.begin(), vec.end(),
[value](typename T::value_type i){ return i < value;}
);
}
int main()
{
std::vector<int> vector = {1, 2, 3, 4, 5, 2, 2, 2};
std::cout << countLessThan(vector, 3) << '\n';
return 0;
}
Any kind soul know how to correct the following code
"d1.insert(d1.begin(), it[0]);" so the the output is as follow:
program will run successfuly and display: 1 2 3 4 5 6 7 8 9 10
#include <list>
#include <deque>
#include <iostream>
using namespace std;
template<typename T> ostream & print(const T & start, const T & end)
{
T tmp = start;
for(; tmp != end; ++tmp)
{
cout<< *tmp<< " ";
}
return cout;
}
class A
{
public:
int a;
public:
A(int a):a(a) {}
A(const A & a) {}
};
ostream & operator<<(ostream & c, const A & o)
{
c<<o.a;
return c;
}
int main()
{
int tab[]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
list<A> l1(tab, tab+10);
deque<A> d1;
list<A>::iterator it;
for(it = l1.begin(); it != l1.end(); ++it)
{
d1.insert(d1.begin(), it[0]);
}
print(d1.begin(), d1.end())<<endl;
return 0;
}
It seems from the code that you want to insert to a std::deque not a std::list (you already inserted the array values into the list l1). You could follow the same procedure to insert to the std::deque:
int main(void) {
int tab[] = { 1,2,3,4,5,6,7,8,9,10 };
std::list<int> l1(tab, tab + 10);
std::deque<int> d1(tab, tab + 10);
}
where I have simply replaced A by int here as the former looks just to be a wrapper for an int.
Alternatively you could do,
int main(void) {
int tab[] = { 1,2,3,4,5,6,7,8,9,10 };
std::list<int> l1(tab, tab + 10);
std::deque<int> d1;
auto it = d1.begin();
d1.insert(it, l1.begin(), l1.end());
}
An alternative is just to use std::copy:
#include <algorithm>
#include <iterator>
//...
std::copy(l1.begin(), l1.end(), std::back_inserter(d1));
There are other issues with your code you should correct:
1) Remove the empty A copy constructor. By making it empty, you're creating A copies that will not copy the a member.
2) The parameter to the A constructor should be different than the name of the member variable.
See the Live Example
This question already has answers here:
Why is there no transform_if in the C++ standard library?
(11 answers)
Closed 8 years ago.
Which algorithm or combine of algorithms can use for following situation?
struct Term
{
int ix;
double f;
};
std::vector<Term> terms = <intitalize terms>;
std::vector< int > termIxVector;
// NEED get all `ix` from the `terms` where term.f < 1.0,
// and insert 'ix' result to termIxVector.
//i.e. equavalent this loop:
for(std::size_t i = 0; i < terms.size(); ++i)
if ( terms[i].f < 1.0 )
termIxVector.push_back(terms[i].ix);
std::copy_if copies only Term structure. std::transform - doesn't support predicate.
Use std::for_each with a lambda
std::for_each(terms.begin(), terms.end(),
[&termIxVector](Term const& t) {
if(t.f < 1.0) termIxVector.push_back(t.ix);
});
Or a range based for
for(auto const& t : terms) {
if(t.f < 1.0) termIxVector.push_back(t.ix);
}
These kind of compositions of elementary algorithms are most conveniently done with Boost.Range:
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <iostream>
#include <iterator>
#include <vector>
struct Term
{
int ix;
double f;
};
int main()
{
using namespace boost::adaptors;
auto terms = std::vector<Term>{ {0, 0.1}, {1, 1.1}, {2, 0.8}, {3, 1.2}, {4, 0.9} };
auto termIxVector = terms
| filtered([](auto const& x){ return x.f < 1.0; }) // select
| transformed([](auto const& y){ return y.ix; }) // project
;
boost::copy(termIxVector, std::ostream_iterator<int>(std::cout, ","));
}
Live Example using Clang 3.5 SVN which prints the indices 0, 2, and 4 of your Term elements having a double less than 1.0.
NOTE: these ranges are lazily computed, and termIxVector is not a std::vector<int> actually. If you want that, you need to do something like
std::vector<int> termIxVector;
boost::push_back(termIxVector, /* RHS of the same range composition as above */);
If you really want to use std::copy_if, then an idea is to overload operator int() in the struct and use the standard std::copy_if with a unary predicate (lambda or functor), as this will allow you to convert Term to int. Code below:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
struct Term{
int ix;
double f;
operator int(){
return ix;
}
};
struct predicate{ // if you don't want a lambda
bool operator()(const Term& t){
return (t.f < 1.0 ? true : false);
}
};
int main()
{
std::vector<Term> terms = {{1, 0.1}, {2, 0.2}, {3, 1.1}, {4, 0.9}};
std::vector< int > termIxVector;
std::copy_if(terms.begin(), terms.end(),
back_inserter(termIxVector), predicate());
for(auto& elem: termIxVector)
std::cout << elem << std::endl;
}