Creating a swatch library - c++

Hey all, I'm working on cleaning up my code from previous semesters.
Previously I created a 151 color swatch library in c++. However because of my time crunch and lack of experience, I created it entirely as a block of define statements. Which, for hard coding values into spots worked fine. However there are some obvious weaknesses to this approach.
What I have panned out so far, is to create a namespace 'swatch' and inside the namespace I would have an enumeration for the valid colors. I would also have a 'getSwatch' function, or something similar, that would return a vec3 (a class of mine, represents a vector of 3 elemets, with some nice functionality), and the function would use a switch statement to go through the valid swatches.
It would look something like this:
namespace swatch{
enum color{
red,
blue,
green
}
inline
const vec3 getColor(const color& c){
// Switch and return red blue or green.
}
}
My Question: I'd like to know how you might suggest doing this? Benifits of preformance, and usability is what I'm most interested in.
Thanks in advance friends,
Happy coding.
Edit: I just changed the example to make more sense to people who don't know how I use my vec class. (i.e: Everybody but me). Also, you can just look at the other anwsers for usage. They made a good guess on passing rgb values to the constructor, thats not how I did it, but I can still follow along just fine with what you mean.

Use a lookup table:
/************* .h *************/
enum color{
red,
blue,
green,
colors_count
}
const vec3 &getColor(color c)
{
extern const vec3 colors_table[colors_count];
return colors_table[c];
}
/************* .cpp *************/
extern const vec3 colors_table[colors_count] = {
vec3(255, 0, 0), // red
vec3(0, 0, 255), // blue
vec3(0, 255, 0), // green
};
You didn't write anything about purpose of using templates so I just eliminated them. If you explain more then I will help maybe.
// EDIT
It's very simple and very fast.
In c++, enum values are not just some identifiers, they are numbers. If you don't specify other they will be fallowing numbers starting from 0: 'red' is 0, 'blue' is 1, 'green' is 2 and 'colors_count' is 3 (see http://www.google.com/search?q=c%2B%2B+enum).
You can use these numbers to index an array. Then you simply pick an item from an array at given index.

You could just use a std::map<color, vec>:
class ColorClass {
private:
std::map<color, vec> colors;
// ... etc ...
And then you have a big init function that sets it up:
colors["red"] = new vec(0xFF, 0x00, 0x00);
colors["blue"] = new vec(0x00, 0xFF, 0x00);
// ... etc ...
And then your getColor function is just:
return colors[color];
Done!

Related

how to understand the syntax `Color (&EnumValuesColor())[3] {...}`?

this is an auto generated header (by flatbuffer serializer) and I've never seen any syntax like Color (&EnumValuesColor())[3] {...} could someone explain it ?
enum Color {
Color_Red = 0,
Color_Green = 1,
Color_Blue = 2,
Color_MIN = Color_Red,
Color_MAX = Color_Blue
};
inline const Color (&EnumValuesColor())[3] {
static const Color values[] = {
Color_Red,
Color_Green,
Color_Blue
};
return values;
}
const Color (&EnumValuesColor())[3]
is an old-fashioned way of writing
auto EnumValuesColor() -> Color const (&)[3]
which makes it clearer that EnumValuesColor is a function. To read the return type, we read inside out, and right to left, which gives the return type as: a reference to an array of 3 const Color objects.
It's not surprising that you don't recognise it; this is an example of some very arcane declarator shenanigans we inherited from C, relating to the so-called "spiral rule".
What's happening here is:
There is a function called EnumValuesColor
It returns a reference to an array of 3 const Colors
It's marked inline
You can use https://cdecl.org to help you parse super-complex declarations like this, though note that you'll have to replace Color with int, otherwise it won't know you're talking about a type:
Since C++14, you may prefer to write the function declaration like this instead:
inline auto& EnumValuesColor() {
static const Color values[] = {
Color_Red,
Color_Green,
Color_Blue
};
return values;
}
Now, in such a small function, just by observing that we directly return a const Color values[] (and mentally stick a 3 in there) we can see much more easily what the heck is going on. I am definitely not one of those people who recommends "auto almost always", but this seems like a great use case for it.
As an aside, if you were wondering why bother using a function at all… that's probably to avoid the static initialisation order fiasco. The initialisation of function statics is a gazillion times more predictable than for anything declared at namespace scope.

Can I define a static map as a function argument in the actual function call?

UPDATE: I just did some benchmarking of the core conversion logic for various solutions. Here are the CPU times in nanoseconds for a single iteration, averaged out of five million iterations on Wandbox:
8 - switch statement
176 - static map
3800 - dynamic map
As you can see, creating a new map every time (dynamic mapping) is relatively time consuming. Creating the map once (static mapping) and just referring to it thereafter is almost 22 times faster. But, coincidentally, the original switch-based solution is 22 times faster than static mapping!
Hmm... I never considered dynamic mapping a viable solution but had hopes for static mapping. It's quite a bit slower than the good, old switch statement, but does 8 nanoseconds versus 176 nanoseconds really matter?
End of update
The core problem I'm trying to solve is translating from one "namespace" to another (in the general sense, not re the C++ namespace keyword). This is common in programming, usually solved in C++ with a switch statement like this:
#include <iostream>
enum MUSIC { ROCK, RAP, EDM, COUNTRY };
enum COLOR { RED, BLUE, ORANGE, WHITE };
COLOR convert(MUSIC music)
{
COLOR color = WHITE;
switch (music) {
case RAP: color = RED; break;
case EDM: color = BLUE; break;
case ROCK: color = RED; break;
}
return color;
}
int main()
{
COLOR c = convert(COUNTRY);
std::cout << c << std::endl;
}
The following is my solution (the templates will be tucked away in a header file somewhere). The convert() function works with any types that are valid for std::map, e.g., enum to enum and long to std::string. The first parameter is the key, or "from" value, the second is the default value if can't be converted, and the return value is the mapped, or "to," value. (Special thanks to #Yakk for help with template argument deduction.)
#include <iostream>
#include <map>
#include "boost/assign.hpp"
template<class T> struct no_deduction { typedef T type; };
template<typename Key, typename T>
T convert(const Key &k, const T &d, const typename no_deduction<std::map<Key, T> >::type &m) {
typename std::map<Key, T>::const_iterator it = m.find(k);
return it == m.end() ? d : it->second;
}
using boost::assign::map_list_of;
enum MUSIC { ROCK, RAP, EDM, COUNTRY };
enum COLOR { RED, BLUE, ORANGE, WHITE };
int main()
{
COLOR c = convert(COUNTRY, WHITE, map_list_of (RAP, RED) (EDM, BLUE) (ROCK, RED));
std::cout << c << std::endl;
}
Anyway, notice that map_list_of, above, creates the same list every time it's called. I'd like it to be static. This is the obvious solution:
static const std::map<MUSIC, COLOR> m = map_list_of (RAP, RED) (EDM, BLUE) (ROCK, RED);
COLOR c = convert(COUNTRY, WHITE, m);
But I'm trying to make it simple to use, in particular, as a single statement. Here's a macro solution, but I'd rather avoid that, too.
#define CONVERT(f,t,d,m) do{static const std::map<BOOST_TYPEOF(f), BOOST_TYPEOF(d)> m_ =\
map_list_of m; t = convert(f, d, m_);}while(0)
COLOR c;
CONVERT(COUNTRY, c, WHITE, (RAP, RED) (EDM, BLUE) (ROCK, RED));
Does anybody know of some C++ magic (C++03, actually) that can call my convert() function
with a static map,
as a single statement, and
without using a macro?
Why not just simply use a static array and index it ?
enum MUSIC { ROCK = 0, RAP = 1, EDM = 2, COUNTRY = 3 };
enum COLOR { RED, BLUE, ORANGE, WHITE };
static const COLOR music_to_color[] =
{
RED, //maps to 'ROCK = 0'
BLUE, //maps to 'RAP = 1'
ORANGE, //maps to 'EDM = 2'
WHITE //maps to 'COUNTRY = 3'
};
MUSIC music = RAP;
std::cout << music_to_color[music] << std::endl;
The body of your convert function can be only return music_to_color[music] (where music would be the argument) in this case.
The advantages of this approach are speed and lack of additional runtime overhead of creating a std::map of something simmilar. Disadvantage would be the fact that you cannot easily modify the map on runtime and it is more "C-like" than "C++ like" (you can ease the pain using std::array instead of static array if you need C++ interface: iterators, etc.)
Another way to do the same thing is to use template specializations, but it is a lot of typing and it would be difficult to maintain if you had a lot of values to map.
Uppercase names are conventionally reserved for macros, so I renamed them.
At some point you are going to have to do the work of coding how one enum type converts to another. The easiest way using a map is as follows:
Color convert(Music music)
{
static const std::map<Music, Color> converter = { { Rap, Red }, { Edm, Blue }, { Rock, Red } };
return converter.at(music);
}
This uses initializer lists which is a C++11 feature. If you can't use that, you can try:
Color convert(Music music)
{
static const struct Once
{
Once()
{
converter[Rap] = Red;
converter[Edm] = Blue;
converter[Rock] = Red;
}
std::map<Music, Color> converter;
} once;
std::map<Music, Color>::const_iterator find_it = once.converter.find(music);
assert(find_it != once.converter.end());
return find_it->second;
}
This code might not use fancy macros but it's safe, reasonably efficient (one instance of the map) and readable (although I did do a trick with that struct there). There are faster ways but they are more complicated and probably not necessary for your use case.
If there are less than a dozen enum values, I would consider just using a switch statement however. It is usually faster than a map.

How do I create an immutable static public object within a class?

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.

Accessing to enum values by '::' in C++

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;

How to generate new QColors that are different

I wish to have a large array of QColors that many classes will share and index from.
In the past, I've always had the list like such:
QColor colours[10] = {QColor("cyan"), QColor("magenta"), QColor("red"),
QColor("darkRed"), QColor("darkCyan"), QColor("darkMagenta"),
QColor("green"), QColor("darkGreen"), QColor("yellow"),
QColor("blue")};
However, now I want many more than 10. How can I create a large list of different QColors?
if you want your list to be dynamic, I would use some sort of QVector instead, wrapped in a Color Manager for example :
class ColorManager
{
public:
ColorManager(size_t iDefaultSize)
{
m_colorList.reserve(iDefaultSize);
}
void addColor(const QColor& c)
{
m_colorList.push_back(c);
}
QColor& operator[](int iIndex)
{
return m_colorList.at(iIndex);
}
private:
QVector m_colorList;
};
If your colors have to be unique, consider using a QSet, but you loose the [] operator as QSet are ordered structure, and you will have to implement a find in ColorManager, using QSet::find(). It will also be slower.
If it has to be thread safe, you can eventually protect it with QMutex.
Also, I don't know why you need this, but you should have a look at :
QColorGroup and / or QPalette
Here is a good article on randomly generating colors from sets so that they look good together.
http://devmag.org.za/2012/07/29/how-to-choose-colours-procedurally-algorithms/
qsrand(time(0));
QColor(qrand()%255, qrand()%255, qrand()%255)
You can use the QColor constructor which takes red, green and blue parameters to create new colors as:
QColor colours[10] = {QColor(255,0,0), QColor(0,255,0), QColor(0,0,255),
QColor(0,0,0), QColor(255,255,255),
QColor(0,128,64)};
You can use as many possible combinations of r,g,b to come up with new colors. You can find the Red, Green and Blue parameters for different colors by looking at Pantone color table and create a nice set of matching colors for your application.