I get a queue of events which must contain a class with generic variables. In order to do that I tried to use the tuples. I used variadic templates to generate my tuples but I can't put them in my queue because of their types which aren't the same. Could you give me some advise about how to do this?
#include <type_traits>
#include <iostream>
#include <vector>
#include <iostream>
#include <tuple>
#include <utility>
#include <queue>
class Logs
{
public:
Logs() {}
template <class T, class... Values>
void write(T data, Values&&... values) {
auto save = std::tuple_cat(_t, std::make_tuple(data)); // I would like to save the return in a variable class
write(values...);
}
void write() {
// the end
// _queue.push(save);
}
std::tuple& getTuple() { return _t;}
private:
std::tuple<> _t;
std::queue<std::tuple<>> _queue;
};
#include <iostream>
int main(int ac, char **av) {
Logs log;
Logs log2;
log.write(4, "42");
log.write(Logs(), 4.5f, 42, "toto");
log.write({"hello", "titi"}, 84, "foo");
// std::cout << std::get<0>(log.getTuple()) << std::endl;
return 0;
}
Which could be the type of _t and _queue ?
I would like to push in my queue get one time a std::tuple<int, std::string, Log. float, ...> then a std::tuple<std::vector<std::string>, int, long>, etc. .
You could use a union as the type of your std::queue, like this:
#include <iostream>
#include <queue>
typedef union Data {
int i;
float f;
char str[20];
struct foo {
int a;
char c;
} foo;
struct bar {
int a;
double d;
} bar;
} data;
int main () {
std::queue<data> q;
data mydata;
mydata.i = 5;
q.push(mydata);
data mydata1;
mydata1.f = 3.14;
q.push(mydata1);
data mydata2;
strcpy(mydata2.str, "foo");
q.push(mydata2);
data mydata3;
mydata3.foo.a = 1;
mydata3.foo.c = 'a';
q.push(mydata3);
data mydata4;
mydata4.bar.a = 7;
mydata4.bar.d = 2.78;
q.push(mydata4);
int i = 0;
while(!q.empty()) {
if(i == 0) {
std::cout << ' ' << q.front().i;
} else if(i == 1) {
std::cout << ' ' << q.front().f;
} else if(i == 2) {
std::cout << ' ' << q.front().str;
} else if(i == 3) {
std::cout << ' ' << q.front().foo.a << " " << q.front().foo.c;
} else if(i == 4) {
std::cout << ' ' << q.front().bar.a << " " << q.front().bar.d;
} else {
std::cout << "I do not know what the item has\n";
}
q.pop();
++i;
}
return 0;
}
However, consider that you can not easily use an std::string for example inside a union, either a std::tuple, thus you have to re-think if you can give a shot for the boost::variant, because as you see the code is becoming easily non-maintainable.
Related
#include <iostream>
#include <vector>
#include <string>
#include <any>
#include <map>
#include <functional>
#include <exception>
using namespace std;
using MapAny = std::map<string, any>;
int square(int x) {
return x*x;
}
vector<int> parse(map<string, vector<MapAny>> mapping)
{
vector<MapAny> func_square = mapping["square"];
vector<int> res;
for (const auto &mapany : func_square) {
try {
int x = any_cast<int>(mapany.at("x"));
res.push_back(square(x));
}
catch (exception e) {
vector<int> xs = any_cast<vector<int>>(mapany.at("x"));
for (int x : xs) res.push_back(square(x));
}
}
return res;
}
int main()
{
map<string, vector<MapAny>> function_map_value, function_map_array;
function_map_value = {
{"square", { {{"x", 5}}, {{"x", 10}} }}
};
vector<MapAny> vec;
vec.push_back({{"x", vector<int>({5, 10}) }});
function_map_array = {
{"square", vec}
};
vector<int> res1 = parse(function_map_value);
vector<int> res2 = parse(function_map_array);
for (int i=0; i<res1.size(); i++) cout << res1[i] << " "; cout << "\n";
for (int i=0; i<res2.size(); i++) cout << res2[i] << " "; cout << "\n";
return 0;
}
I'm trying to make a function parser that can accept any type, such as both scalar and vector values, like in Python dict().
However, I'm not sure how to check if a std::any object has type std::vector. In the code above, if any_cast fails, it will throw exception and I know it's a std::vector. It's ugly and rely on throwing exception as an expected behavior.
How can I change the above code into something like:
if (is_vector(mapany.at("x")) {
// deal with vector
}
else {
// deal with scalar
}
I want to write a program which reads names in a vector. After that it should read ages into another vector. (that's done)
The first element of the name-vector should be connected to the first element of the age-vector, so if I use any kind of sort() function on the name-vector the age-vector gets sorted as well.
Is there any way to realize this in an easy way?
class Name_pairs {
public:
//member functions
int read_names();
int read_ages();
int print();
private:
vector<double> age;
vector<string> name;
};
int Name_pairs::read_names() {
cout << "Please enter different names, you want to store in a vector:\n";
for (string names; cin >> names;) {
name.push_back(names);
}
cin.clear();
cout << "You entered following names:\n\t";
for (int i = 0; i < name.size(); i++) {
cout << name[i] << " \n\t";
}
return 0;
}
int Name_pairs::read_ages() {
cout << "\nPlease enter an age for every name in the vector.\n";
for (double ages; cin >> ages;) {
age.push_back(ages);
}
return 0;
}
I think you need a std::vector of a coupled type.
struct Name_pair {
double age;
string name;
};
Than you can use std::vector<Name_pair> and use a lambda
auto comparator = [](const Name_pair& first, const Name_pair& second){return first.age <second.age;};
to sort your vector with std::sort.
Name_pairs = std::vector<Name_pair>;
// fill vector
std::sort(Name_pairs.begin(), Name_pairs.end(), comparator);
Here is a working example.
#include <vector>
#include <algorithm>
#include <string>
#include <iostream>
struct Name_pair {
double age;
std::string name;
};
int main() {
std::vector<Name_pair> Name_pairs{{13, "Hallo"}, {32, "Welt"}, {1, "Georg"}};
auto comparator = [](const Name_pair& first, const Name_pair& second) { return first.age < second.age; };
std::sort(Name_pairs.begin(), Name_pairs.end(), comparator);
for (const auto np : Name_pairs) {
std::cout << np.name << "\n";
}
}
It prints
Georg
Hallo
Welt
If you want to implement a data-oriented design by using separate vectors instead of a single vector of classes, you could use a vector of indeces and sort it.
The following is just an example:
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
class Customers
{
std::vector<double> ages_;
std::vector<std::string> names_;
template <typename Comparator>
auto make_indeces(Comparator &&comp)
{
std::vector<size_t> indeces(names_.size());
std::iota(indeces.begin(), indeces.end(), 0);
std::sort(indeces.begin(), indeces.end(), comp);
return indeces;
}
template <typename Type>
void reorder_vector(std::vector<Type> &src, std::vector<size_t> const &indeces)
{
std::vector<Type> tmp;
tmp.reserve(src.size());
std::generate_n(
std::back_inserter(tmp), src.size(),
[&src, idx = indeces.cbegin()] () mutable {
return src[*(idx++)];
});
src = std::move(tmp);
}
public:
void add(std::string const &name, double age)
{
names_.push_back(name);
ages_.push_back(age);
}
void sort_by_names()
{
auto indeces = make_indeces([this] (size_t i, size_t j) {
return names_[i] < names_[j];
});
reorder_vector(names_, indeces);
reorder_vector(ages_, indeces);
}
void show_sorted_by_ages()
{
auto indeces = make_indeces([this] (size_t i, size_t j) {
return ages_[i] < ages_[j];
});
for (auto i : indeces)
std::cout << names_[i] << ' ' << ages_[i] << '\n';
}
void show()
{
for (size_t i = 0; i < names_.size(); ++i)
std::cout << names_[i] << ' ' << ages_[i] << '\n';
}
};
int main(void)
{
Customers c;
c.add("Adam", 23);
c.add("Eve", 21);
c.add("Snake", 66.6);
c.add("Apple", 3.14);
std::cout << "Sorted by ages (doesn't modify the internal order):\n";
c.show_sorted_by_ages();
std::cout << "\nInternal order:\n";
c.show();
c.sort_by_names();
std::cout << "\nInternal order after sorting by names:\n";
c.show();
}
Testable HERE.
I've been trying to think of a way to have my class method take an arbitrary number of callback functions, run all of them, and then store the output. I think this works, but is there a way I can do this where I don't have to make the user wrap all of the callback functions into a vector? This also just feels messy. Feel free to mention other things that are not ideal.
#include <iostream>
#include <functional>
#include <vector>
class MyObj{
public:
// where I store stuff
std::vector<double> myResults;
// function that is called intermittently
void runFuncs(const std::vector<std::function<double()> >& fs){
if ( myResults.size() == 0){
for( auto& f : fs){
myResults.push_back(f());
}
}else{
int i (0);
for( auto& f : fs){
myResults[i] = f();
i++;
}
}
}
};
int main(int argc, char **argv)
{
auto lambda1 = [](){ return 1.0;};
auto lambda2 = [](){ return 2.0;};
MyObj myThing;
std::vector<std::function<double()> > funcs;
funcs.push_back(lambda1);
funcs.push_back(lambda2);
myThing.runFuncs(funcs);
std::cout << myThing.myResults[0] << "\n";
std::cout << myThing.myResults[1] << "\n";
std::vector<std::function<double()> > funcs2;
funcs2.push_back(lambda2);
funcs2.push_back(lambda1);
myThing.runFuncs(funcs2);
std::cout << myThing.myResults[0] << "\n";
std::cout << myThing.myResults[1] << "\n";
return 0;
}
Something like this, perhaps:
template <typename... Fs>
void runFuncs(Fs... fs) {
myResults = std::vector<double>({fs()...});
}
Then you can call it as
myThing.runFuncs(lambda1, lambda2);
Demo
I'm trying to re-write some MatLab code in C++ and I've come across this:
currentsign = sign(vector(i));
I have looked on the internet and found this link: http://www.mathworks.co.uk/help/techdoc/ref/sign.html
I'm just wondering if there's a sign function in C++? If not, can anyone suggest any tutorials on creating it.
Thank you :)
template <typename T>
int sign (const T &val) { return (val > 0) - (val < 0); }
Credit due to Ambroz Bizjak.
template <typename T>
std::vector<int> sign (const std::vector<T> &v) {
std::vector<int> r(v.size());
std::transform(v.begin(), v.end(), r.begin(), (int(*)(const T&))sign);
return r;
}
Full example on ideone.
I would suggest
First, write a function of functor that takes a single element and returns 1, -1 or 0 depending on the element's value
Second, use std::transform together with this function/functor to take an input container and fill a second container with the desired values
template <typename T>
int signum(const T& val) {
// implement signum logic
}
#include <vector>
#include <algorithm>
int main() {
std::vector<int> data = ....;
std::vector<int> signs(data.size());
std::transform(data.begin(), data.end(), signs.begin(), signum<int>);
}
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <vector>
inline int get_signum(int val) {
return val < 0 ? -1
: val == 0 ? 0
: 1;
}
int main() {
std::vector<int> values;
for (int i = -5; i < 6; ++i)
values.push_back(i);
std::vector<int> signum(values.size());
std::transform(values.begin(), values.end(), signum.begin(), get_signum);
for (int i = 0; i < values.size(); ++i) {
std::cout << std::setw(2) << values[i] << ' ' << signum[i] << std::endl;
}
return 0;
}
Well You can do It at compile time using template Specialization.
You can use sign<n>::Positive, sign<n>::Negetive and sign<n>::Zero also you can use sign<n>::Sign which is 1|0|-1 which is same as sign of Matlab.
#include <iostream>
template<int n>
struct sign{
enum{
Positive = (n > 0),
Negetive = (n < 0),
Zero = 0,
Sign = ((n > 0) ? 1 : -1)
};
};
template<>
struct sign<0>{
enum{
Positive = 0,
Negetive = 0,
Zero = 1,
Sign = 0
};
};
int main(){
std::cout << sign<0>::Positive << sign<0>::Negetive << sign<0>::Zero << sign<0>::Sign << std::endl;
std::cout << sign<1>::Positive << sign<1>::Negetive << sign<1>::Zero << sign<1>::Sign << std::endl;
std::cout << sign<-1>::Positive << sign<-1>::Negetive << sign<-1>::Zero << sign<-1>::Sign << std::endl;
return 0;
}
You used to do sign(n) there and here you will do sign<n>::Sign.
C99 has signbit() and copysign(), which seem to be implemented in glibc on Linux. You didn't specify what platform you're on though, so I'm not sure that helps...
I want to store 3 integer in priority_queue. I know how to store 2 integer.
I store 2 integer with pair<int,int>
my code
priority_queue<pair<int,int> , vector<pair<int,int> > , greater<pair<int,int> > > pq;
pq.push(make_pair(5,6));
but I don't know how can I store 3 integer. I need help.
sorry for my English.
Simplest would be create a struct which logically binds all the integers and create a priority queue of that struct objects.
EDIT
Sample code:
#include <queue>
using namespace std;
struct S
{
int m_n1;
int m_n2;
int m_n3;
S(int n1, int n2, int n3) : m_n1(n1), m_n2(n2), m_n3(n3)
{
}
bool operator<(const struct S& other) const
{
//Your priority logic goes here
return m_n1 < other.m_n1;
}
};
int main()
{
priority_queue<S> pq;
//Add the elements to the queue
pq.push(S(1,2,3));
pq.push(S(4,2,3));
pq.push(S(2,2,3));
//This element will be S(4,2,3)
S s1 = pq.top();
pq.pop();
return 0;
}
or the easy way: std::pair<int,std::pair<int,int>>
You may use Boost::Tuple
#include "boost/tuple/tuple.hpp"
#include <queue>
#include <vector>
#include <iostream>
typedef boost::tuple<int, int, int> triple_t;
class my_greater {
public:
bool operator() (const triple_t& arg1, const triple_t& arg2) const
{
return arg1.get<0>() > arg2.get<0>();
return false;
}
};
typedef std::priority_queue<triple_t, std::vector<triple_t>, my_greater>
my_priority_queue;
int main()
{
my_priority_queue triples;
triples.push(boost::make_tuple(1,2,3));
triples.push(boost::make_tuple(10,20,30));
triples.push(boost::make_tuple(5,10,15));
triples.push(boost::make_tuple(15,30,45));
triples.push(boost::make_tuple(2,4,6));
std::cout << "Result: \n";
while (!triples.empty())
{
const triple_t& t = triples.top();
std::cout << t.get<0>() << ", " << t.get<1>() << ", " << t.get<2>() << std::endl;
triples.pop();
}
return 0;
}