How to override the default struct constructor - d

I have a struct that needs to keep track of the number of created instances and uses it as a unique ID. Hence in the default constructor I need to update a static variable such as this:
struct Wire {
int x, y, id;
static int instanceCount;
this() {
this.id = instanceCount++;
}
}
I do not wish to disable the default constructor. Currently I am using a class to work-around it.

Those are your options in D. Use a class and be able to define no-argument constructors, or use a struct and not be able to do this. The reasons for it apparently have to deal with D's .init functionality. Another workaround would be to use a separate factory function that constructs Wire, updates instanceCount, and returns Wire.
What you're doing sounds like makes much more sense with classes, anyway. It's more expected for classes to have 'instances' and class state like instanceCount. If you only want structs so that you can allocate them on the stack, you can actually do this with classes: scope s = new S()

As #verne already point outyou should use classes for that. Another way is use static opCall, but it is not perfect solution:
import std.stdio;
struct Wire {
int x, y, id;
static int instanceCount;
static opCall() {
Wire w;
w.id = instanceCount++;
return w;
}
}
void main()
{
auto s0 = Wire();
auto s1 = Wire();
writeln(s0);
writeln(s1);
}

Related

Store Templated data type in a struct

We are using a PubSub framework that uses template methods to register topics and identify as a publisher or subscriber. For example, to register a topic name in the system you'd call:
RegisterTopic<T>(std::string topicName);
I would like to be able to create a parameter list (or configuration list if you will) to identify the needed registration topics in use by a given application configuration using a simple struct like
struct RegistrationTopicType
{
std::string name;
int type; // replace with some mechanism to store a data type
};
However I haven't found a working mechanism to replace the int in the struct above with something to store a data type.
I'm trying to do this so that I can maintain a list of topics and their types in the system:
std::vector<RegistrationTopicType> topicList = {
{"topic1", MyClass},
{"topic2", MyOtherClass}, // and on and on.
};
which I could use later do things like call the templated Registration method.
for (auto & topic : topicList) {
RegisterTopic<topic.type>(topic.name);
}
I have experimented with templated struct where I tried to store the data type such as
template<typename T>
struct TemplatedRegistrationTopic
{
using DataType = T;
std::string name;
};
But while I can implement instances of this struct,
TemplatedRegistrationTopic <float> topic{"floatTopic"};
TemplatedRegistrationTopic <MyClass> topic{"MyClassTopic"};
I can't seem to access the "DataType" variable as a datatype to use in the Registration method.
RegisterTopic<topic.DataType>(topic.name); // this fails.
I saw somewhere to use '::' but that also fails:
Register<topic::DataType>(topic.name); // this also fails.
Problems of storing a bunch of topics of different types in a common list aside, is what I'm trying to do (store a data type for later use in a templated method) even possible?
In the ol' days I might have created an enum list with an enum for of the possible types and then used that to select the actual type in a massive switch statement, but I don't want to have to maintain a mapping between all of the possible types and an enum in a giant switch statement which seems to defeat the purpose of using templates. eg I don't want to end up with this, but its effectively what I'm trying to do:
enum typelist { Type1, Type2 }; // one for each type that might be used as a topic
struct EnumRegistrationTopicType
{
std::string name;
typelist type;
};
std::vector<EnumRegistrationTopicType> enumTopicList = {
{"topic1", Type1},
{"topic2", Type2}, // and on and on.
};
for (auto & topic : enumTopicList) {
switch (topic.type) {
case typelist::Type1:
RegisterTopic<MyClass1>(topic.name);
break;
case typelist::Type2:
RegisterTopic<MyClass2>(topic.name);
break;
}
}
Let's do a classic OO design.
struct RegistratorBase {
virtual ~RegistratorBase() = default;
virtual void doRegistration(const std::string& topic) const = 0;
};
template <typename T>
struct Registrator {
void registerTopic(const std::string& topic) const override {
doRegistration<MyClass1>(topic);
}
};
struct RegistrationTopicType {
std::string name;
std::unique_ptr<RegistratorBase> registrator;
}
Now you can add these things to a vector
std::vector<RegistrationTopicType> topicList {
{ "topic1", new Registrator<MyClass1> },
{ "topic2", new Registrator<MyClass2> },
};
and register everything
for (const auto& topic: topicList) {
topic.registrator->doRegistration(topic.name);
}
Of course now one starts to wonder, why is RegistrationTopicType needed at all? Why not shove the name directly to the Registrator? OK let's try:
struct RegistratorBase {
virtual ~RegistratorBase() = default;
// no need for other virtual members
};
template <typename T>
struct Registrator {
Registrator (const string& topic) {
RegisteerTopic<T>(topic);
}
};
Nice! Now let's put this into a vector:
std::vector<std::unique_ptr<RegistratorBase>> topicList {
new Registrator<MyClass1>("topic1"),
new Registrator<MyClass2>("topic2")
};
Great! But why do we need a vector of these things? We construct the vector of registrators and never use it anymore. Why not just create a bunch of variables instead?
Registrator<MyClass1> r1("topic1");
Registrator<MyClass2> r2("topic2");
But that's not really different from a list of function calls:
RegisterTopic<MyClass1>("topic1");
RegisterTopic<MyClass2>("topic2");
So variables are not needed either, nor are their classes. Put the calls somewhere and you are done. They are your configuration list.
We have successfully designed, simplified, and finally eliminated a totally redundant software component!
Perhaps some of the simplification steps will not be applicable to your case, in which case the component will not be redundant for you. But I have no way of knowing that.

How to modify the same variable in different classes and modify it?

I have many function definitions which I have placed in different cpp files with function declarations in their respective .h files.
I have a set of a variables which I have placed in a .h file. These variables need to modified by different functions. I am using static to keep the changes from each function, but I heard it is a bad coding practice. How else to do it ? For eg -
variables.h
class variable{
static int x;
static int y;
};
function1.h
class function(){
public:
void function1();
}
similar for function 2
function 1.cpp
void function1(){
// does something with x and y (used as (variable::x=2;variable::y=3)
}
function2.cpp
void function2(){
// does something with x and y (used as variable::x+=2;variable::y+=2)
}
main.cpp
int variable::x;
int variable::y;
int main(){
obj.function1(); (obj is object of function1 class)
obj2.function2(); (obj2 is object of function2 class)
cout << variable::x << variable::y << endl;
}
I was was using different objects in different cpp files but changes in one function were not reflecting in other. How it use it please help?
You can simply move these variables into another class:
struct Shared {
int x;
int y;
};
Now you can pass an instance to this class as parameter to your function, this is called dependency injection:
void foo(Shared& shared) {
shared.x = 4;
shared.y = 2;
}
This is better because you don't have any global state anymore. You could use the function multiple times independent from each other by referencing a different instance of the Shared class.
It is very common to take this a step further by "injecting" the instance in the constructor of that class. This is helpful if the instance of that class should always reference the same instance:
struct Foo {
Shared& m_shared;
Foo(Shared& shared)
: m_shared(shared)
{
}
void foo() {
m_shared.x = 4;
m_shared.y = 2;
}
};
Yes, as you mentioned using static variable for this purpose is kind of anti-pattern. A better pattern (without knowing the background of the application) is using a composition pattern. If your functions f1() and f2() are in classes C1 and C2, you would e. g. create an additional data object D1 (with the variables in question), and inject and object of D1 in the constructor of C1 and C2, so both classes operation on a data object. There are also other solutions to this situation, but I guess thats the most general. Google for C++ Design Pattern to find more general patterns.
You can use smart pointers for global objects
struct MyGlobal
{
std::shared_ptr<Core> core;
MyGlobal(){ core=std::make_shared<Core>(); }
void changeVariableX(int X)
{
core->X = X;
}
};
You can move, copy, do whatever you want with MyGlobal instances and they still point to same core item. Just make sure all of them are populated from same instance like this:
int main()
{
MyGlobal global;
auto something = useSomeFunctionWith(global);
auto somethingElse = useAnotherFunctionWith(global);
...
// use something and somethingElse to change X, both point to the same X
}
If functions will not be thread-safe then you should add a lock-guard into changeVariableX method.

Can a C++ class's default value be changed at runtime?

In C++ is it possible to change the default values of a class so that all future objects made of that class will have the values specified?
I am trying to make a class that is user-defined at run time that should function nearly identical to other child of the same parent class, but I am struggling with a way to have the same format constructor exist across both. The only way I can think to properly funnel the correct information to every new object is to have either the class type be always treated differently on creation (always put in the user inputs into the constructor) or have the class's object behavior on creation change to default to the inputs defined.
Edit: To better explain the issue and address the XY problem possibility here is the scenario:
General Program:
I want to have the user first define a custom shape by providing a name and the number of lines that define it. The user then can add triangles, squares and the custom shape to their "cart". Each custom shape is the same shape that they specified at the start, the user does not change it during the program. The program could then return general information such as the number of members of a specific type that exists or the total number of lines in the cart.
There is a parent class:
Class Shape
member numLines, name;
And three classes are children of Shape:
Class Triangle
overwritten numLines = 3, name = "triangle";
...
Class userShape
overwritten numline = ????, name = ????;
When I create methods for the cart that interact with "shape" objects I would like to be able to have the same code across the board for creating additional objects, instead of needing to treat the userShape's constructor differently.
From the answers I have received, the static type seems to best fit the user-setting of the default values but I am entirely open to better ways to implement something like this.
Just because you can, doesn't mean you should. Now that I got that out of the way, here's how:
#include <iostream>
struct C {
static int default_val;
C(int i = default_val) {
std::cout << i << '\n';
}
};
int C::default_val = 0;
int main() {
C c;
C::default_val = 1;
C c2;
return 0;
}
A default argument to a function doesn't have to be a constant expression, it just has to be "available" at every place the function is called. And a static variable is just that.
It also doesn't have to be accessible at the call site. So if you want the class to control it, but not have it be modifiable from outside the class, you can make it private.
I would recommend following the next pattern:
Run your application
Read/Load the configuration
Create a factory for that object from that configuration
Use the factory to create more instances of the same object throught the lifetime of your application
For example:
struct Object {
Object(int x, int y) : _x(x), _y(y) {}
int _x, _y;
};
struct DynamicFactory {
DynamicFactory(int x, int y) : _x(x), _y(y) {}
std::shared_ptr<Object> generate() { return std::make_shared<Object>(_x, _y); }
int _x, _y;
};
int main(){
// Load configuration
// Initialize dynamic factory using configuration
DynamicFactory factory(1, 3);
// Generate objects
auto obj1 = factory.generate();
auto obj2 = factory.generate();
return 0;
}
Try to use static members so these are shared across the objects.

How to pass a membervariable as variable itself

Imagine you have a class with 100 or more member variables:
class DataContainer { int a1; int a2; ... double a100; };
and another class which accesses and analysis parts of the variables in the first class:
class Analysis {
protected:
DataContainer *myData;
void myVar1, myVar2;
public:
Analysis() {...}
void myChoice(void a, void b) { myVar1 = a; myVar2 = b }
void Analyse(DataContainer data) {
myData = data;
/* do something with myVar1 and myVar2 */
}
};
but before analysing you have to choose which parameters to use. I would like to know how to write a call for this myChoice-function which is not simply passing the content of a variable, but the choice of the membervariable itself.
In order to ask more generally: I think the position in the memory of a class-member relatively to the class itself is fixed (is it?) Independet if it is a new instance of that class or not. So how can I tell the combiler "Please use the membervariable a3 always". Instead of the content of a3.
This is exactly what pointers-to-data-members are for.
int DataContainer::* myVar1 = &DataContainer::a1;
double DataContainer::* myVar2 = &DataContainer::a100;
I think the position in the memory of a class-member relatively to the class itself is fixed (is it?)
It is indeed. The relative position does not change at run time. This is why pointers-to-data-members work. They can be implemented as a memory offset.
PS. Considering how massive DataContainer is, I would not recommend passing it by value if you can avoid it.
PPS. Consider grouping the member variables into sub-structures.
If the purpose is to have a way to select specific fields in known ways, based on the type of analysis you are doing, then make Analyze virtual pure, and have specific types of analysis pick their fields directly.
From the question, I get the idea that you want to perform the same underlying computation, but use different data points based on the myChoice.
So the whole issue is how do you create the selection metadata? If there are a few specific, well documented ways to do it, then providing each in a subclass will be a very clear, concise and maintainable approach.
class Analysis {
public:
virtual void Analyze(const DataContainer &data) = 0;
virtual ~Analysis();
protected:
void special_computation(int x, int y, double z);
};
class SpecificKindOfAnalysis : public Analysis {
public:
void Analyze(const DataContainer &data){
int x = data.a27;
int y = data.a12;
double z = data.a99;
special_computation(x,y,z);
}
};
This actually looks pretty horrible with variable names like x = data.a27, but I assume we're trying to be general here, and the actual program has meaningful names.

Is it possible to make a factory in C++ that complies with the open/closed principle?

In a project I'm working on in C++, I need to create objects for messages as they come in over the wire. I'm currently using the factory method pattern to hide the creation of objects:
// very psuedo-codey
Message* MessageFactory::CreateMessage(InputStream& stream)
{
char header = stream.ReadByte();
switch (header) {
case MessageOne::Header:
return new MessageOne(stream);
case MessageTwo::Header:
return new MessageTwo(stream);
// etc.
}
}
The problem I have with this is that I'm lazy and don't like writing the names of the classes in two places!
In C# I would do this with some reflection on first use of the factory (bonus question: that's an OK use of reflection, right?) but since C++ lacks reflection, this is off the table. I thought about using a registry of some sort so that the messages would register themselves with the factory at startup, but this is hampered by the non-deterministic (or at least implementation-specific) static initialization order problem.
So the question is, is it possible to implement this type of factory in C++ while respecting the open/closed principle, and how?
EDIT: Apparently I'm overthinking this. I intended this question to be a "how would you do this in C++" since it's really easy to do with reflection in other languages.
I think that the open/closed approach and DRY are good principles. But they are not sacred. The goal should be making the code reliable and maintainable. If you have to perform unnatural acts to adhere to O/C or DRY, then you may simply be making your code needlessly more complex with no material benefit.
Here is something I wrote a few years ago on how I make these judgment calls.
You do not need to make your code follow every possible principle simultaneously. The aim should be to stick to as many of those paradigms as possible and no more. Do not over-engineer your solution -- you are likely to end up with spaghetti code otherwise.
I have answered in another SO question about C++ factories. Please see there if a flexible factory is of interest. I try to describe an old way from ET++ to use macros which has worked great for me.
The method is macro based and are easily extensible.
ET++ was a project to port old MacApp to C++ and X11. In the effort of it Eric Gamma etc started to think about Design Patterns
You could convert classes that create messages (MessageOne, MessageTwo ...) into message factories and register them with top level MessageFactory on initialization.
Message factory could hold map of MessageX::Header -> instance of MessageXFactory kind of map.
In CreateMessage you would find instance of MessageXFactory based on message header, retrieve the reference to MessageXFactory and then call it's method that would return instance of the actual MessageX.
With new messages you no longer have to modify the 'switch', you just need to add an instance of new MessageXFactory to the TopMessageFactory.
example:
#include <iostream>
#include <map>
#include <string>
using namespace std;
struct Message
{
static const int id = 99;
virtual ~Message() {}
virtual int msgId() { return id; }
};
struct NullMessage : public Message
{
static const int id = 0;
virtual int msgId() { return id; }
};
struct MessageOne : public Message
{
static const int id = 1;
virtual int msgId() { return id; }
};
struct MessageTwo : public Message
{
static const int id = 2;
virtual int msgId() { return id; }
};
struct MessageThree : public Message
{
static const int id = 3;
virtual int msgId() { return id; }
};
struct IMessageFactory
{
virtual ~IMessageFactory() {}
virtual Message * createMessage() = 0;
};
struct MessageOneFactory : public IMessageFactory
{
MessageOne * createMessage()
{
return new MessageOne();
}
};
struct MessageTwoFactory : public IMessageFactory
{
MessageTwo * createMessage()
{
return new MessageTwo();
}
};
struct TopMessageFactory
{
Message * createMessage(const string& data)
{
map<string, IMessageFactory*>::iterator it = msgFactories.find(data);
if (it == msgFactories.end()) return new NullMessage();
return (*it).second->createMessage();
}
bool registerFactory(const string& msgId, IMessageFactory * factory)
{
if (!factory) return false;
msgFactories[msgId] = factory;
return true;
}
map<string, IMessageFactory*> msgFactories;
};
int main()
{
TopMessageFactory factory;
MessageOneFactory * mof = new MessageOneFactory();
MessageTwoFactory * mtf = new MessageTwoFactory();
factory.registerFactory("one", mof);
factory.registerFactory("two", mtf);
Message * msg = factory.createMessage("two");
cout << msg->msgId() << endl;
msg = factory.createMessage("one");
cout << msg->msgId() << endl;
}
First, your system is not so open ended, since you switch on an 8-bit char, so your message type count won't exceed 256 ;-)
Just joking apart, this is a situation I'd use a little templated factory class (stateless if you put your char message type in a non-class template arg, or with just that char as state) that accepts your stream& and does the new on its T template arg, passing the stream& and returning it. You'll need a little registrar class to declare as static with global scope, and register the concrete T-instantiated factory (via an abstract base class pointer) with a manager (we have a generic one that takes a "factory domain" key). In your case I wouldn't use a map but directly an 256 "slot" array to put the factory_base* in.
One you have the factory framework in place, it's easy and reusable. --DD