I am trying to add serial support for an existing class in SFML library. I am trying to save colors to be loaded later. From the documents, it says that Cereal is easily extensible to other types, but I have no clue how to do so. Barring creating a SerialColor class and reimplementing sf::Color inside it, and adding a serialize member in there, is there a way to do this? I would really like to not rewrite the 5 classes I need from SFML to be serializeable.
I am part way through converting Color to SerialColor, and so far have achieved the following:
SerialColor.hpp
#pragma once
#include <SFML/Graphics.hpp>
#include <SFML/Config.hpp>
class SerialColor: sf::Color
{
public:
static const SerialColor Black; ///< Black predefined color
static const SerialColor White; ///< White predefined color
static const SerialColor Red; ///< Red predefined color
static const SerialColor Green; ///< Green predefined color
static const SerialColor Blue; ///< Blue predefined color
static const SerialColor Yellow; ///< Yellow predefined color
static const SerialColor Magenta; ///< Magenta predefined color
static const SerialColor Cyan; ///< Cyan predefined color
static const SerialColor Transparent; ///< Transparent (black) predefined color
SerialColor(sf::Uint8 red, sf::Uint8 green, sf::Uint8 blue, sf::Uint8 alpha = 255);
private:
SerialColor(sf::Color c);
sf::Color color;
template<class Archive>
void serialize(Archive& archive, std::uint32_t const version) {
archive(CEREAL_NVP(this->color.r),
CEREAL_NVP(this->color.g),
CEREAL_NVP(this->color.b)
);
}
};
SerialColor.cpp
#include "SerialColor.h"
SerialColor::SerialColor(sf::Uint8 red, sf::Uint8 green, sf::Uint8 blue, sf::Uint8 alpha = 255) {
this->color = sf::Color(red, green, blue, alpha);
}
SerialColor::SerialColor(sf::Color c) {
this->color = sf::Color(c);
}
This is currently not completely implemented, so it does not work. However this feels like overkill to add 1 function to a class. If extending is the correct way, could you provide what is considered the normal way to add this capability? This just feels wrong.
Instead of trying to extend the class directly, you can provide cereal with a function that tells it how to serialise your custom data types, e.g:
namespace cereal {
template<class Archive>
void serialize(Archive& archive, sf::Color c) {
archive(CEREAL_NVP(c.r),
CEREAL_NVP(c.g),
CEREAL_NVP(c.b)
);
}
You can choose to add something like the code above to your own header file (something like 'Serialize.hpp') and include that instead of cereal.hpp, or you can extend your cereal headers directly (i.e. something like cereal/types/sf_color.hpp).
It's really up to you where you put this code but as long as it is visible, cereal will automatically be able to serialise the sf::Color type.
Related
Im trying to make a class called Label. Labels are plain text controls. One should be able to change the text and color of a label through get/set functions. I think this is a way to change the text of the label through get/set function. But Im not sure about the color. Any advice would be appriciated.
<pre>
class Label
{
private:
std::string text;
int color;
public:
Label();
void SetText(string Ntext);
void SetColor(int value);
int GetColor();
string GetText();
~Label();
};
<code>
<pre>
Label::Label()
{
}
string Label::GetText()
{
return text;
}
void Label::SetText(string Ntext)
{
text = Ntext;
}
int Label::GetColor()
{
return color;
}
void Label::SetColor(int value)
{
color = value;
}
Label::~Label()
{
}
<code>
You can make color an array containing red blue and green.
int color[3];
void SetColor(int red, int green, int blue){
this->color[0] = red;
this->color[1] = green;
this->color[2] = blue;
}
Besides the question of how to represent the color (which actually varies depending on how the class will be used, for example, it can be something as simple as red, black, white, etc strings), another thing to consider is that having getters and setters is not good in terms of OOP.
The idea of OOP is to hide the data inside the objects and instruct these objects to do something useful (send them messages).
With getters and setters you open the internal implementation (it is actually the same as if you define the text and color as public properties. It doesn't sound good, right? But this is actually what it is, you can read and modify them as if they are public.
So the better implementation could be to have both text and color to be constructor parameters. This way label has enough information to be displayed, so you don't need to have setters / getters, something like this:
class Label
{
private:
std::string text;
int color;
public:
Label(string text, string color);
~Label();
// display the label on the `canvas`
void display(Canvas* canvas);
};
More information on the topic of getters / setters:
Why getter and setter methods are evil
More on getters and setters
Getters/Setters. Evil. Period.
Consider the following Enum Class in Java:
package com.gousslegend.deepov;
public enum Color
{
WHITE, BLACK;
private Color opposite;
static
{
WHITE.opposite = BLACK;
BLACK.opposite = WHITE;
}
public Color getOppositeColor()
{
return opposite;
}
}
How can I achieve the same thing with C++11?
Is is possible to have enum methods with C++11?
Should I put my enum in a separate class/file with C++?
Thanks
How can I achieve the same thing with C++11?
In C++ you would be better off defining an enum, along with a free-standing function:
enum Color {BLACK, WHITE};
Color getOppositeColor(Color c) {
static Color opposite[] = {WHITE, BLACK};
return opposite[c];
}
If you are set on modeling Java exactly, make a class with two static members BLACK and WHITE, and use it instead of enum. The use would be limited, though: for instance, you wouldn't be able to use your enum values in switch cases.
Is is possible to have enum methods with C++11?
No
Should I put my enum in a separate class/file with C++?
You should put enum definition and a function prototype in a header; implementation of the function goes in a separate C++ file.
C++'s enums are simple enumerated values, they're not full-fledged classes (enum classes in C++ only provide some additional type-safety).
I would take the following approach to implement the equivalent to how Java's enums are used here:
// Header file
class Color {
Color *opposite_p;
public:
Color(Color *opposite_pArg) : opposite_p(opposite_pArg) {}
Color &opposite() { return *opposite_p; }
static Color WHITE, BLACK;
};
// .C file
Color Color::WHITE(&BLACK);
Color Color::BLACK(&WHITE);
Then, Color::WHITE.opposite() returns Color::BLACK, and COLOR::BLACK.oppsoite() returns Color::WHITE.
I have a class Color that holds values for the red, green, blue, and alpha channels of a color. The class constructor lets you create a new color by specifying values for the four channels. However, for convenience, I would also like to have some "premade" colors available for the programmer. For example instead of having something like
DrawBox(new Color(255, 0, 0));
you would be able to say
DrawRectangle(Color::Red);
Where Color.Red is an instance of Color that lives inside the Color class. How can I declare these instances of Color inside the Color class? I'm sure there's a name for this technique, but I had no idea what search terms to use when I was looking for help online.
I'm not using any built-in or publicly-available classes or libraries because this is part of a personal exercise in creating a basic graphics stack.
Thanks for your help!
First of all, avoid using new. You could use Color as simple value-type.
Now as an answer to your question, yes, you can do that as:
//color.h
typedef unsigned char byte;
class Color
{
public:
//declaration
const static Color Red;
const static Color Green;
const static Color Blue;
public:
Color(byte red, byte green, byte blue);
};
//define the static members in color.cpp file
#include "color.h"
const Color Color::Red(255,0,0);
const Color Color::Green(0,255,0);
const Color Color::Blue(0,0,255);
Then use Color::Red as you want to use.
I have class like following:
class Car
{
public:
Car();
// Some functions and members and <b>enums</b>
enum Color
{
Red,
Blue,
Black
};
Color getColor();
void setColor(Color);
private:
Color myColor;
}
I want to:
access to Color values as Color::Red. It is really hardly to understand code when Car::Red is used, when class have a lot enums, subclasses etc.
use type Color as function argument or return value
use variable type Color in switch
I know 3 partial solutions:
Using embedded class Color and enum in it
Using embedded namespace Color and enum in it
Using enum class
1 and 2 solutions solves a Color::Red accession problem, but I can't use functions like Color getColor() and void setColor(Color).
3 solution has a problem: VS2010 doen't support enum class. GCC v.4.1.2 doesn't support it too. I don't know about later versions of gcc.
Yes, I'm working on cross-platform project.
I have found this solution, but it seems ... heavy.
I hope somebody can help me here :)
In current C++ (i.e. C++11 and beyond), you can already access enum values like that:
enum Color { Red };
Color c = Color::Red;
Color d = Red;
You can go further and enforce the use of this notation:
enum class Color { Red };
Color c = Color::Red;
// Color d = Red; <-- error now
And on a sidenote, you now define the underlying type, which was previously only possible with hacky code (FORCEDWORD or so anyone?):
enum class Color : char { Red };
Name the enum inside the nested class (as example one):
class Car
{
public:
struct Color
{
enum Type
{
Red,
Blue,
Black
};
};
Color::Type getColor();
void setColor(Color::Type);
};
When I want to do something like this I tend to use a namespace and a typedef outside of th namespace (though usually I'm doing this globally rather than inside a class). Something like this:
namespace colors
{
enum Color
{
Red,
Blue
...
}
}
typedef colors::Color Color;
This way you use the namespace to get at the actual colors, but the Color type itself is still globally accessible:
Color myFav = colors::Red;
Suppose I have a code as following.
class Color
{
static Color a;
public:
static Color newColor(int r,int g,int b){
Color color;
color.setR(r);
color.setG(g);
color.setB(b);
return color;
}
}
Is it alright to initialize the static variable 'a' using 'Color a = Color::newColor(255,0,0);'
I think I read somewhere that creating the instance using this method will create two instances of the class. What is the right way of doing this?
Yes Color gets instantiated twice
the local variable color in newCOlor and
the static Color a (since you are returning an object, a member-wise copy will happen at the static variable definition/initialization).
Be sure to put Color::a = Color::newColor(255,0,0); in a cpp/cc file, meaning not in a header file.
Try this for size:
struct Color
{
int R, G, B;
};
Color a = {255, 0, 0};