Making a vector to hold multiple types

Hello, someone on a C++ Discord suggested I do this:


#include <variant>

using ImageOrVideo = std::variant< Image, Video >;

but when I try in my header file:

#pragma once

#include "ofMain.h"
#include "ofxDSHapVideoPlayer.h"
#include "ofxMidi.h"
#include "ofxGui.h"
#include <variant>

using PhotoOrVideo = std::variant<ofImage, ofxDSHapVideoPlayer>;

I get an error “namespace std has no member variant”. So I guess variant is not a function in the version of C++ that oF uses… Any good suggestions for how to do this in oF?

I was also wondering if I shouldn’t make a third class that both inherit from so I can make a third type to hold both…

Hey s_e_p,

indeed std::variant is introduced in → C++17.

You can use C++17 in oF, but support for it out of the box is just now merged into master, so you would have to wait until the next release, or get the nightly.
If you don’t have experience with C++, I would recommend to wait for the release. While the nightly is fairly stable, you might always run into a couple of issues that are being worked on at the moment.

Apart from that you could indeed get the same functionality (if not even a bit easier to handle in the end) with inheriting classes.
I would probably not inherit from both classes at the same time, but use a base class to put in the vector and have two derived classes that each implement either image or video logic.

1 Like

Maybe you can do it using
boost::any or std::any
I never used them, not sure if it works for you.

Hey, I tried your idea…

class VidOrPhoto
{
private:
	bool isVid; //else is 
public:
	VidOrPhoto(bool isVideo)
	{
		isVideo = isVid;
	}

	bool isVideo()
	{
		return isVid;
	}
};

class Video : public VidOrPhoto
{
private:
	ofxDSHapVideoPlayer video;
	ofFmodSoundPlayer audio;
public:
	void load(const string& vPath, const string& aPath)
	{
		video.load(vPath);
		audio.load(aPath);
	}
	void play()
	{
		video.play();
		audio.setPaused(false);
		audio.play();
	}
	void pause()
	{
		video.pause();
		audio.setPaused(true);
	}
	void update()
	{
		video.update();
	}
	void draw(const ofRectangle& rect)
	{
		video.draw(rect.x, rect.y, rect.width, rect.height);
	}
	bool isPlaying()
	{
		return video.isPlaying();
	}
};

class Photo : public VidOrPhoto
{
private:
	ofImage photo;
public:
	void load(const string& path)
	{
		photo.load(path);
	}
	void draw(const ofRectangle& rect)
	{
		photo.draw(rect);
	}
	bool isAllocated()
	{
		return photo.isAllocated();
	}
};

Now, when I write this

shared_ptr<Video> v = make_shared<Video>(true);
				map<string, string>::iterator it = m_avDictionary.find(p);
				v->load(p, it->second);
				v->play();
				shared_ptr<VidOrPhoto> vop = v;
				m_vidsOrPhotos[is] = vop;

it seems to work. However, once I get it in the vector, I can’t get it back out as a Video to get access to its Video functions…

Maybe try a class that has both an image and a video player in it. It could inherit from one (maybe the video player) and have the other as a class member. Or both could be class members with no parent classes. You could add some additional members that describe which one if active. I’ve don’t think I’ve made a class that inherits from 2 or more parents.