0

So i am trying to make class Bed inherit from class Device. I know the constructor is called with an int, Socket class and Ini class; the thing i dont know is whether or not more arguments are passed of different classes.

thats what im trying to do here in my Bed.cpp file:

#include "Bed.h"
#include <fstream>
#include <string>
#include <sstream>
#include <iostream>
#include <unistd.h>
#include <string>
#include <vector>
#include "Socket.h"
#include "Ini.h"

using namespace std;

class Socket;
class Ini;

template <typename... Types> Bed<Types...>::Bed(int number, Socket s, Ini i, const Types&... var): id(number), socket(s), ini(i) {
    if (typeid(var).name() == "Button") {
        buttons_.push_back(var);
    } else if (typeid(var).name() == "Led") {
        leds_.push_back(var);
    } else if (typeid(var).name() == "RGBled") {
        rgbleds_.push_back(var);
    } else {
        cout<<"error"<<endl;
    }
}

template <typename... Types> void Bed<Types...>::check() {
    for (int i = 0; i <= buttons_.size() - 1; i++) {
        buttons_[i].getStatus();
    }
    getPressure();
}

template <typename... Types> void Bed<Types...>::getPressure() {

}

this is my Bed.h file:

#ifndef BED_H_
#define BED_H_

#include <string>
#include <vector>
#include <iostream>
#include <cstdarg>

using namespace std;

class Device;
class Socket;
class Ini;

template <typename... Types> class Bed: public Device {
public:
    Bed(int, Socket, Ini, const Types...);
    void getPressure();
    void check();
private:
    int pressureSensor = 0;
};

#endif

and this is my Device.h file:

#ifndef DEVICE_H_
#define DEVICE_H_

#include <string>
#include <vector>
#include <iostream>
#include <cstdarg>

using namespace std;

class Button;
class Led;
class RGBled;
class Socket;
class Ini;

template <typename... Types> class Device {
public:
    //Device(int, Socket, Ini, const Types&...);
    virtual void check();
    //virtual ~Device();
private:
    vector<Led> leds_;
    vector<Button> buttons_;
    vector<RGBled> rgbleds_;
    Socket socket;
    Ini ini;
    int id;
};

#endif

In my Bed.cpp, I get the error

declaration is incompatible with "Bed::Bed(int, Socket, Ini, Types...)" (declared at line 17 of "/home/programmer/project/Bed.h")

which is the line

Bed(int, Socket, Ini, const Types...);

I've been trying to fix this for hours now, and at this point I've got no clue anymore.

Obsidian
  • 3,719
  • 8
  • 17
  • 30
Ryan
  • 1
  • 2
  • Unrelated, but see [why-can-templates-only-be-implemented-in-the-header-file](https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file). – Jarod42 Dec 22 '19 at 18:07
  • 1
    As state in error message, you have typo in declaration: missing reference in `Bed(int, Socket, Ini, const Types...);` (-> `Bed(int, Socket, Ini, const Types&...);`). – Jarod42 Dec 22 '19 at 18:09
  • definition is also wrong... variadic not expanded. – Jarod42 Dec 22 '19 at 18:10
  • Thanks for the answers, but i dont understand completely. what do you mean with variadic not expanded? also i changed the Types... to Types&... in Bed.h and it didnt do anything – Ryan Dec 22 '19 at 18:36
  • You have lot of errors, so harder to answer your (post) question as-is (and one fix will just jump to next error, which might be interpreted as wrong fix). For variadic not expended: you have `const Types&... var`, so `var`is a variadic variable, but, you use it as regular variable: `if (typeid(var).name() == "Button") `. – Jarod42 Dec 22 '19 at 18:46

1 Answers1

0

One way of getting at this problem would be to let your Device have an add_component function that can add a Led/Button/RGBLed to the vectors. You could then forward your type-pack to that function.

template <typename... Types> class Device {
public:
    //Device(int, Socket, Ini, const Types&...);
    virtual void check();
    //virtual ~Device();
    void add_component(Led led); { leds_.push_back(led); }
    void add_component(Button button); { buttons_.push_back(button); }
    void add_component(RGBled rgbled); { rgbleds_.push_back(rgbled); }
private:
    vector<Led> leds_;
    vector<Button> buttons_;
    vector<RGBled> rgbleds_;
    Socket socket;
    Ini ini;
    int id;
};

template <typename... Types> Bed<Types...>::Bed(int number, Socket s, Ini i, const 
Types&... var): id(number), socket(s), ini(i) {
    (add_component(var), ...);
}

(add_component(var), ...); is a folding expression and will unfold to

(add_component(var1), add_component(var2), ..., add_component(varN));

Overload resultion in the three add_component methods will take care of adding the component to the right vector.

Since it don't know what these types are, the components are passed by value here. A sensible default if the thing is very cheap to copy. Inconsistent with the constructor that takes the arguments by cont-ref, but sorting the details of that out is left as an exercise to the reader.

super
  • 12,335
  • 2
  • 19
  • 29
  • Thanks! I never knew that you could do that, it actually makes it a lot more elegant. The problem still remains though, it seems the constructor implementation in Bed.cpp doesnt recognise Socket and Ini classes. Any further help is much appreciated! – Ryan Dec 22 '19 at 19:12
  • I'm very new to this, so don't know what you mean with "Inconsistent with the constructor that takes the arguments by cont-ref, but sorting the details of that out is left as an exercise to the reader." I'm glad to clarify my code if something is unclear. – Ryan Dec 22 '19 at 19:16
  • As mentioned in the comment by Jarod42 you need to put the implementation of a template in the header. You can't have it in a separate `.cpp` file. In addition to that you have `const Types&...` in the .cpp file and `const Types...` in the .h file. Not the same, `&` on one and not the other. – super Dec 22 '19 at 20:36
  • Thanks for the clarification. Based on your advise I've now got: `Bed(int number, Socket s, Ini i, const Types&... var); { id = number; socket = s; ini = i; (add_component(var), ...); }` inside de Bed.h file – Ryan Dec 22 '19 at 22:12
  • I've now got the error `argument list for class template "Device" is missing` inside the Bed.h file where i forward declare class Device, which is annoying. If anybody knows the answer or has a link I'd greatly appreciate it. – Ryan Dec 22 '19 at 22:23
  • @Ryan From the code you shown there is no real need for `Device` to be a template. The error tells you that you need to specify the template parameters for it when you inherit. `class Bed: public Device`. But maybe you could just let `Device` be a non-template class if you don't actually need to know the types there. – super Dec 22 '19 at 23:31