2

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. .

gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • 2
    You can use [boost::variant](http://www.boost.org/doc/libs/1_58_0/doc/html/variant.html). – huu Jul 20 '15 at 12:37
  • 5
    Don't repeat a question. Improve the original question if it was badly phrased, or set a bounty if it is hard and you don't get enough attention. – Kerrek SB Jul 20 '15 at 12:38
  • I know boost::variant but as it's for an embedded program boost is a too big library :( – Gabrielle de Grimouard Jul 20 '15 at 12:39
  • 1
    I agree with @KerrekSB. In your case, I would bet that you need to rephrase your question. It's not clear *at all*. Also, I would suggest to avoid boost, I do not think there is need for a library. – gsamaras Jul 20 '15 at 12:39
  • Why do you don't understand ? I don t understand what is unclear – Gabrielle de Grimouard Jul 20 '15 at 12:40
  • 2
    Where exactly is your problem. In the insertion, right? But what would you like to do exactly and it's failing? – gsamaras Jul 20 '15 at 12:42
  • I get a queue which need to put tuples with different variables. The problem is with the type of my queue which is variable. So I would like to get something like a queue which don't need type a the compile time and same for the tuple but all in a class. – Gabrielle de Grimouard Jul 20 '15 at 12:44
  • I add calls to the write function in my example to get it clearer. my main problem is in the types of _t and _queue – Gabrielle de Grimouard Jul 20 '15 at 12:47
  • 2
    So, you want a queue, where every item of the queue may be different from the other element? – gsamaras Jul 20 '15 at 12:50
  • Yes it's what I want :D – Gabrielle de Grimouard Jul 20 '15 at 12:51
  • 1
    Now a question: would it be at all possible to define a small hierarchy or types that you _might_ have in your queue, and use polymorphism: a queue of the abstract type? –  Jul 20 '15 at 13:03
  • @Boris That's why I change the name of my post fez minutes ago to rename it into "generic types in a queue" and add lots of explanations in my question. I'd never be good to explain what I want. – Gabrielle de Grimouard Jul 20 '15 at 13:03
  • And a comment: if you have trouble explaining to humans what you are trying to do, explaining it to a computer is going to be even more trouble, don't you think? (PS: [this is a fez](https://en.wikipedia.org/wiki/Fez).) –  Jul 20 '15 at 13:04
  • About types I can indeed chose them but I don't like to do something which could need some futhers modifications :S Moreover I already did it with fixed types @Boris I had already troubles to explain to myself what I want in general xD – Gabrielle de Grimouard Jul 20 '15 at 13:13
  • This is the textbook example of a case where inheritance and polymorphism are meant to be used. BTW, by types I meant C++ `class` or `struct`, which are user-defined types. But obviously this is not good enough for you. –  Jul 20 '15 at 13:19
  • I get an idea with inheritance to get what I want but I can't do this because it's a framework for a research lab so it's have to get simple to use it :( – Gabrielle de Grimouard Jul 20 '15 at 13:22
  • There is no point in putting different types into a queue. Putting data into a queue doesn't *do anything* until you take the data out. Without a description of what you want to do when you take the data out, a program equivalent to yours simply discards all of the information you put into the queue and says "same difference". This may seem academic to you: but how you intend to use the data you are storing is important. So is "how many types you want to store" and other details you are not giving. "etc" requires we read minds. What are you doing with the queue after you populate it? – Yakk - Adam Nevraumont Jul 20 '15 at 15:15
  • @Yakk It's about a framework including configuration files which can be read and write with multiple applications a the same time. The queue avoid the concurency which can cause bugs. As it's a framwork the types have to be generic even if in 99% of cases it will only be basic types. There are others ways to do it but it as to be quite simple for the new developers. Moreover, it was more a theorical question than a real one. – Gabrielle de Grimouard Jul 21 '15 at 08:32
  • Sure. But theoretically, discarding data instead of queuing it is the answer until you add in reading ops. Add reading ops that matxh the need you have (and don't over-specify). When putting generic data somewhere, how you want to use it *exactly* and what *exact* requirements on types stored matters: differences your question ignores or glosses over makes the answer vary from "you cannot do that" to "that is easy". – Yakk - Adam Nevraumont Jul 21 '15 at 11:18
  • @Yakk there is a reading ops. Not in my example but the core application is reading the queue and change the configuration files. The exact answer of my question is that I cannot do that because of template which are done at the compile time. – Gabrielle de Grimouard Jul 21 '15 at 11:30
  • You are not an expert (unless you became one in the day or so since you asked the question), and you have not shown enough information here that others can say "this cannot be done". So if you are certain your problem (the queue, not some specific technical details about it) cannot be solved, you should not be. This is a common problem on stack overflow. – Yakk - Adam Nevraumont Jul 21 '15 at 12:10
  • I can't give more information because I get a contract which not allow me so explain precisely what I'm working for. My problem can be solved and I solved it easly but it's a framework for non real developer so I can't do exacly what I want to because it have to be easy of use. I don't know what you want to mean by insinuate that I'm a beginner but I know what I'm talking about. – Gabrielle de Grimouard Jul 21 '15 at 12:20

1 Answers1

2

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.

Community
  • 1
  • 1
gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • I already did an union before but the problem is that it's quite limited for a framework because I can't think about all the types the users wish to use. I also though about inheritance but that is still complicated for users to use it. I won't add boost in my project because it's for an embedded applicaiton an boost is too big. I'm thinking about to recode the boost::variant of QVarriant. – Gabrielle de Grimouard Jul 20 '15 at 13:32
  • You used a union and you didn't mention that in your question? And I was coding for you, in something you already didn't want? http://f1.thejournal.ie/media/2013/11/lie_down__try_not_to_cry__cry_a_lot_combo_by_badflippy-d5t596e-630x322.jpg Anyway, I think, I answered your question (+1, because it made me refresh my memory for unions), so now you should consider your next step @GabrieldeGrimouard. – gsamaras Jul 20 '15 at 13:34
  • It's not the answer I would but yeah you answered it. I think I can't get a perfect answer to my question so thanks you for your time. :) – Gabrielle de Grimouard Jul 20 '15 at 13:38
  • Have you considered [`boost::any`](http://www.boost.org/doc/libs/1_58_0/doc/html/any.html) or [`std::experimental::any`](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3804.html)? They allow you to store any type in a type safe manner. A user could insert their own class in the queue because any erases type complewtely (it is recoverable with typeid). My understanding is you want an open type safe union. – emsr Jul 20 '15 at 19:20
  • As I already said in comment I don t want to add the libboost in an embedded project. – Gabrielle de Grimouard Jul 20 '15 at 20:04