I'm trying to figure out how I can "pass default struct values" to a function without initializing the struct, this is what I have now:
struct Color3i
{
Color3i(): r(255), g(255), b(255) { }
int r, g, b;
};
void CCore::Color(Color3i color)
{
double red, green, blue;
red = color.r / 255.0f;
green = color.g / 255.0f;
blue = color.b / 255.0f;
glColor3f(red,green,blue);
}
Color3i defaultColor;
Core.Color(defaultColor);
What I'm trying to do would look like this but this clearly doesn't work:
Core.Color(Color3i defaultColor);
How would I pass the struct to the function without initializing it with Color3i defaultColor; is this possible?
Sorry if this has been asked before but I tried searching the interwebs but I couldn't find anything (maybe I'm using the wrong keywords to search)
You should just be able to do this:
Core.Color(Color3i());
That is, call the default constructor to initialize a new instance, and pass it.
There are a few ways to pass an information that you want the color to be default. The simplest one is given in the comments already:
Core.Color(Color3i())
If you want the code to be shorter, you can set the default value in the function parameter you invoke:
void CCore::Color(Color3i color = Color3i()) { ... }
....
Core.Color(); //no argument = default
If you want to be more descriptive instead, you can create a static function acting as a constructor in the Color:
struct Color3i {
Color3i(): r(255), g(255), b(255) { }
int r, g, b;
static Colo3i defaultColor() { return Color3i(); }
};
...
Core.Color(Color3i::defaultColor());
Finally, if you want to control the context where the default color can be used, you can create a new dummy enum type and overload the function(s) to accept the default version explicitly:
enum DefaultColorEnum {
DefaultColor
};
void CCore::Color(Color3i color) {
... //normal code
}
void CCore::Color(DefaultColorEnum) { //ignore the parameter value, the type is what matters
Color(Color3i()); //invoke the generic version with default value
}
...
Core.Color(DefaultColor);
It all depends on what you actually wants to achieve...
Related
Suppose I have
enum class Colour
{
red,
blue,
orange
};
class PencilBase
{
public:
virtual void paint() = 0;
};
template <Colour c>
class Pencil : public PencilBase
{
void paint() override
{
// use c
}
};
Now I want to have some factory function to create painters
PencilBase* createColourPencil(Colour c);
What will be the most elegant way to implement this function?
I want to avoid making changes in this function (or its helpers) when I decide to introduce a new colour.
I feel like we have all the information at compile time to achieve this, however I am having trouble to find a solution.
Firstly, you need to know how many colors are there:
enum class Colour
{
red,
blue,
orange,
_count, // <--
};
After you know the number, you can create an array of function pointers of this size, each function creating the respective class. Then you use the enum as an index into the array, and call the function.
std::unique_ptr<PencilBase> createColourPencil(Colour c)
{
if (c < Colour{} || c >= Colour::_count)
throw std::runtime_error("Invalid color enum.");
static constexpr auto funcs = []<std::size_t ...I>(std::index_sequence<I...>)
{
return std::array{+[]() -> std::unique_ptr<PencilBase>
{
return std::make_unique<Pencil<Colour(I)>>();
}...};
}(std::make_index_sequence<std::size_t(Colour::_count)>{});
return funcs[std::size_t(c)]();
}
Template lambas require C++20. If you replace the outer lambda with a function, it should work in C++17 as well.
MSVC doesn't like the inner lambda, so if you're using it, you might need to convert it to a function too. (GCC and Clang have no problem with it.)
I've used unique_ptr here, but nothing stops you from using the raw pointers.
gcc 7.3.1 is not able to handle this code
Here it is, ported to GCC 7.3:
template <Colour I>
std::unique_ptr<PencilBase> pencilFactoryFunc()
{
return std::make_unique<Pencil<I>>();
}
template <std::size_t ...I>
constexpr auto makePencilFactoryFuncs(std::index_sequence<I...>)
{
return std::array{pencilFactoryFunc<Colour(I)>...};
}
std::unique_ptr<PencilBase> createColourPencil(Colour c)
{
if (c < Colour{} || c >= Colour::_count)
throw std::runtime_error("Invalid color enum.");
static constexpr auto funcs = makePencilFactoryFuncs(std::make_index_sequence<std::size_t(Colour::_count)>{});
return funcs[std::size_t(c)]();
}
I don't think there are millions of solutions no ?
PencilBase* createColourPencil(Colour c)
{
switch (c)
{
case Colour::red:
return new Pencil<Colour::red> ();
break;
...
default:
break;
}
}
You have several good possibilities:
PencilBase* createPencil (Colour colour) {
switch (colour) {
case RED:
return new Pencil<RED>();
case BLUE:
return new Pencil<BLUE>();
...
default:
throw std::invalid_argument("Unsupported colour");
}
}
or why not a more modern construct like this one, which has the advantage to be potentially updated at runtime:
std::unordered_map<Colour, std::function<PencilBase*()>> FACTORIES = {
{ RED, [](){ new Pencil<RED>(); } },
{ BLUE, [](){ new Pencil<BLUE>(); } },
...
};
PencilBase* createPencil (Colour colour) {
return FACTORIES[colour]();
}
However, none can completely fullfill what you ask:
I want to avoid making changes in this function (or its helpers) when I decide to introduce a new colour. I feel like we have all the information at compile time to achieve this
There are at least two reasons for this:
Your colour parameter given to your factory is known at runtime, while your template parameter must be known at compile time.
There is no built-in solution to enumerate or go through all enum values
There isn't many solutions to go against the first point, except avoiding templates if you can.
In your case, is there a good reason to use templates ? Do you really need to use a completely different class ? Can't you change your template into a normal parameter passed in the constructor or as a class member ?
If you have no choice to use templates, there exist a way to avoid repeating yourself. You may use good old macros and in a kind of special way commonly called X-macro. Quick example:
colours.hpp:
COLOUR(RED)
COLOUR(BLUE)
COLOUR(ORANGE)
Colour.hpp:
enum Colour {
#define COLOUR(C) C,
#include "colours.hpp"
#undef COLOUR
INVALID_COLOUR
};
Factory function:
PencilBase* createPencil (Colour colour) {
switch(colour) {
#define COLOUR(C) case C: return new Pencil<C>();
#include "colours.hpp"
#undef COLOUR
default:
throw new std::invalid_argument("Invalid colour");
}
}
This will basicly rewrite the switch given as first example. You may as well change the macro to rewrite the mapping. However, as you can see, it may not be more readable or maintainable than to be explicit.
Coming from Java, I am used to doing this:
void setColor(String color) {
this.color = color;
}
However, I recently switched to C++, and I see a lot of this instead:
void setColor(string c) {
color = c;
}
Why not this? Is this not recommended?
void setColor(string color) {
this->color = color;
}
It's the exact same thing. In Java if you had named your parameter c instead of color, you would not have any shadowing and you could easily write
void setColor(String c) {
color = c;
}
The this in Java (or C++ for that matter) is only needed to specify exactly which color you are referring to: the member variable or the local variable.
There is no need to use this, because there is no conflict between local and member variable and no fields are hidden. Generally you don't want this conflict to happen at all by not having same variable as an constructor parameter and also as local variable (despite so many books teach you exactly this).
I find this is much more smooth(and also more readable even if you don't have background from particular language):
private String localColor;
void setColor(String color) {
localColor = color;
}
When using an enum in C++ how does one create getter and setters?
Example:
enum class FieldLayerStates
{
kEmpty = 0, // new to the game.
kActive = 1, // has fields already in the same.
kAdd = 2 // field layer is ready to have a field added.
};
FieldLayerStates _fieldLayerState;
inline FieldLayerStates getFieldLayerState() { return _fieldLayerState; };
inline void setFieldLayerState(FieldLayerStates i) { _fieldLayerState = i; };
I am getting errors at the inline functions:
: Unknown type name 'FieldLayerStates'
: Cannot initialize return object of type 'int' with an lvalue of type 'FieldLayer::FieldLayerStates'
and when I go to use it:
// check the status of the layer to see if it has fields in it already (loaded from CCUserDefaults
if (getFields().empty())
{
// nothing, this must be our first time in.
setFieldLayerStatus(kEmpty);
}
It says kEmpty is undeclared.
Can someone help me clear up my confusion?
You're using an enum class, are you sure that's what you want?
If you stop doing that your code will work.
otherwise refer to FieldLayerStates::kEmpty (because enumerators of an enum class must be qualified by their type name)
I don't know why you get the Unknown type name 'FieldLayerStates' error because you haven't shown enough context to understand the code, at a guess I'd say you're trying to define the functions outside the class and you need to say FieldLayer::FieldLayerStates
Please show the full code so we have a chance of seeing what you're really compiling.
enum class Foo
is a new C++11 language feature that means "strongly typed, and scoped" enumerations. It is significantly different than just
enum Foo
When you use strongly typed enums, you have to qualify them with the scope they are contained in.
enum class Colors { Red, Green, Blue };
enum class Moods { Happy, Bored, Blue };
Without the "class", this won't compile, because you have defined "Blue" twice. With the "Class" you have actually defined two scopes with their own, private, scoped enums, that require the "::" operator to access.
The "class" are also strongly typed, which means that they won't cast - e.g. to an integer type - without you explicitly casting them.
enum COLORS { RED, GREEN, BLUE };
enum class Colors { Red, Green Blue };
int i = RED; // Legal
Colors j = Colors::Red; // Legal
int i = Colors::Red; // Illegal: Colors::Red is not an integer, it's a Colors.
Colors j = Red; // Illegal: You didn't specify the scope.
Colors j = RED; // Illegal: RED is an integer, not a Colors.
for (int i = RED; i <= BLUE; ++i) { cout << i << endl; } // Legal
// But Colors is not a numeric type, you can't do math or increment on it,
// so the following is illegal:
for (auto j = Colors::Red; j <= Colors::Blue; ++j)
enum class Flags = { Herp = 1, Derp = 2 };
Flags combo = Flags::Herp;
combo |= Flags::Derp; // Illegal, no '|' operator for Flags, casting required.
I think you just want this
enum FieldLayerStates
{
kEmpty = 0, // new to the game.
kActive = 1, // has fields already in the same.
kAdd = 2 // field layer is ready to have a field added.
};
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};