Avoid repetitive constructor for user-defined inherited classes - c++

// Library code
struct Entity;
struct Attachment {
Entity& entity;
Attachment(Entity& mEntity) : entity(mEntity) { }
};
// ---
// User code
struct MyAttachment1 : Attachment {
// This is annoying to write for every attachment type
// Especially when there are other constructor arguments
// And if there are a lot of attachment types
MyAttachment1(Entity& mEntity) : Attachment{mEntity} { }
};
struct MyAttachment2 : Attachment {
MyAttachment2(Entity& mEntity) : Attachment{mEntity} { }
};
// ...
As you can see from the code example, every type that derives from Attachment needs to define a repetitive constructor where an Entity& is passed to the base class constructor.
This would not be an issue, but in my projects I deal with 40-50+ attachments, and they also have their own parameters in their constructors.
It seems unnecessary having to explicitly pass Entity& as the first parameter.
One workaround I've found is using a virtual void Attachment::init() method that the user overrides, and that is called by the Entity after an Attachment has been added to it. This, however, uses an unnecessary virtual call and still requires the user to deal with boilerplate code.
Is there a more elegant way to deal with this problem?

No. There is not a more elegant way to write it. I can't even fathom how typing Attachment{mEntity} when you are writing a class constructor can possibly be considered a chore. I mean, you're writing a whole class anyway. If it's such a bother, create a macro in your text editor.

Not sure if it helps, but in C++11 you can also do
struct MyAttachment1 : Attachment {
// Note, this imports ALL of the base constructors, you can't
// pick and choose
using Attachment::Attachment;
};
See https://ideone.com/fceV4k

Related

How do i use parameters with constructors?

I am programming in ue5 and i was creating a spatial hash. i needed to have a declared cell size for the hash, and i decided to use the constructor
Here is a similar code
HSpatialHash.h
UCLASS()
class xxx_API UHSpatialHash final : public UObject
{
GENERATED_BODY()
public:
explicit UHSpatialHash(const float PCellSize) {CellSize = PCellSize;}
}
Error message:
error C:\Users\user\OneDrive\Documents\Unreal Projects\attrition\Source\project name\Private\HSpatialHash.h(18):
error C2338: static_assert failed: 'You have to define UHSpatialHash::UHSpatialHash() or UHSpatialHash::UHSpatialHash(const FObjectInitializer&).
This is required by UObject system to work correctly.'
I tried to add the FObjectInitializer parameter, but it didn't work. I tried to put in in the cpp file, nothing, i don't know what to do. Can you help me?
If you inherit from UObject, you have to provide either a default constructor or the one with the FObjectInitializer parameter. You create the object using NewObject() which does some internal initialization logic for the object and you can't pass parameters to it.
i decided to use the constructor
Depending on what you want to do, you probably should change your decision.
Do you need it to be a UObject with reflection and editor visibility? Because then, it would be easier to just add an "Initialize()" method with the parameters you wanted to have in the constructor and call it after creation, like so:
UCLASS()
class xxx_API UHSpatialHash final : public UObject
{
GENERATED_BODY()
public:
inline void Initialize(const float PCellSize) { CellSize = PCellSize; }
}
and for creation:
UHSpatialHash* spatialHash = NewObject<UHSpatialHash>(this);
spatialHash->Initialize(cellSize);
If you only want it to be a simple class without reflection, you can just use a regular C++ class and use your custom constructor.
Another option would be to use a USTRUCT() instead. It can't do as much as the UCLASS(), but since you do not intent to inherit from it, it may be enough. You can define a custom constructor and do not need to care for the FObjectInitializer parameter.

Passkey idiom with std::make_shared. xmemory cannot access private Key constructor

In my program I need a factory function that provides instances of separate class because I need control over the details of each instance and to be aware of how many instances are in existence at a time. In particular returning a std::shared_ptr is ideal, but this is initially impossible due to a known issue with the "make" fucntions of the std::pointer types as they would need to be friends with my Widget class as well, which isn't portable since it relies on the current implementation of those methods that may change.
To get around this, I want to employ the Passkey idiom, which was directly recommend for this situation as described at the bottom of this: https://abseil.io/tips/134. I also based my implementation off the lessons learned here: https://arne-mertz.de/2016/10/passkey-idiom/
This is a sample project that uses my same setup as my full project:
#include <iostream>
class Widget
{
public:
class Key
{
friend class Factory;
private:
Key() {};
Key(const Key&) = default;
};
int mTest;
explicit Widget(Key, int test) { mTest = test; }
int getTestVar() { return mTest; }
};
class Factory
{
public:
int mTestPass;
Factory(int input) { mTestPass = input; }
std::shared_ptr<Widget> factoryMake() { return std::make_shared<Widget>(Widget::Key{}, mTestPass); }
};
int main()
{
Factory testFactory(10);
std::shared_ptr<Widget> testWidget = testFactory.factoryMake();
std::cout << testWidget->getTestVar();
return 0;
}
However, I get
Error C2248 'Widget::Key::Key': cannot access private member declared in class 'Widget::Key' TestProject ...\include\xmemory 204
This has me completely lost, since the error coming from xmemory.cpp indicates that std::make_shared is sill trying to access a private constructor. As far as I'm aware, the construction of the Key instance occurs within the factoryMake() function, which belongs to Factory, and then that instance is passed into the std::make_shared function; therefore, std::make_shared should not need access to the Key constructor since an already constructed instance is being passed to it, which is the entire point of using this idiom in this context. The class itself is public so it should have no issues interacting with the type Key, only the constructor should be inaccessible.
In the end I can just skip using std::make_shared and instead use the shared_ptr(*T) constructor with a raw pointer, but this is slightly less efficient due to the extra allocation it requires, as noted in my first link. It isn't a big deal as I'm not making many widgets but I'd ultimately prefer to get the more ideal implementation working.
What am I missing here?
The problem is that the compiler needs to copy your Widget::Key when you call std::make_shared, and you have declared the copy constructor private. You can solve this in one of two ways:
Make the copy constructor of Widget::Key public.
Change the Widget constructor to take the Widget::Key by const reference:
explicit Widget(const Key&, ...

do I need to specify class for every function implementation in c++

If I have a header file that states
class fanStatusManager{
public:
//default constructor
fanStatusManager();
public fanstatus_t setFanStatus(fanstatus_t status);
private:
//etc
}`
and a cpp file that implements them:
fanStatusManager::fanStatusManager(){
//default constructor TODOi
}
fanstatus_t fanStatusManager::setFanStatus(fanstatus_t status){
//TODO: imlement this!
assert(false);
}
I get a bit tired of typing "fanStatusManager::" before every implementation. Is it possible to circumvent this somehow?
Although it is possible to avoid typing the name of the class if you place implementation in the header, i.e.
class fanStatusManager{
public:
public fanstatus_t setFanStatus(fanstatus_t status) {
//TODO: imlement this!
assert(false);
}
}
there is no way to work around this if you are implementing member-functions separately. This is because C++ allows free-standing functions, i.e. this syntax is perfectly valid:
fanstatus_t setFanStatus(fanstatus_t status) {
//TODO: imlement this!
assert(false);
}
The above defines a free-standing function called setFanStatus which is not associated with any class.
You can inline the member functions within the class definition
class fanStatusManager
{
public:
//default constructor
fanStatusManager()
{
//default constructor TODOi
};
fanstatus_t setFanStatus(fanstatus_t status)
{
//TODO: implement this!
assert(false);
};
private:
//etc
};
The downside of this is that, whenever you change the implementation of a member function, you are changing the header file that defines the class. That forces recompilation of EVERY compilation unit (aka source file) which depends on the header file.
In practice, unless your project is extremely SMALL and TRIVIAL (e.g. everything lives in a single source file) you are better off NOT doing this, except for very specific cases (e.g. accessors that will never be changed). The effort of typing fanStatusManager will be incurred exactly once for each member function. That is much less significant than the time and boredom you will experience as you get to watch every source file be recompiled when you change the implementation of ANY member function ..... even compilation units that don't actually use the member function you have changed.
If you don't need that class, you can just put it in namespace
namespace fanStatusManager
{
fanstatus_t setFanStatus(fanstatus_s status)
{
...
};
}
and
then you just put at the top of your file
using namespace fanStatusManager;
It won't create any object like class, but i think the functionality should be same. (If you don't need to create an object or work with any properties in that class)

Object Construction in C++

I am working on a small project in C++ that requires me to create an object of a custom class I wrote in another one of my classes. The class is called FIRFilterModule, It has a simple blank constructor.
Being of a java background, my impulse is to create it like this:
class SensorInput{
public:
FIRFilterModule firFilter;
...More Class Members...
SensorInput():firFilter(FIRFilterModule()){}
...};
However this compiles with the ever so helpful error message of "Error within this context". I'm a little lost why that doesn't work. Increasing my confusion I changed the code to this:
class SensorInput{
public:
FIRFilterModule firFilter;
...More Class Members...
SensorInput(){}
...};
It works.
Can someone help me understand why this is so?
In this particular case, running of the default constructor for a member field, you don't have to do anything. The constructor is run automatically. So you can just write
class SensorInput{
public:
FIRFilterModule firFilter;
SensorInput() { ... }
};
The member initialization list is only needed when you need to call a constructor which has arguments or initialize POD types. For example say the FIRFilterModule had a constructor which took an int. Then you would use the memeber initialization list
SensorInput() : firFilter(42) { ... }
The code you posted is correct.
Maybe you forgot to include the header where FIRFilterModule is declared.
Otherwise, everything should work.

Policy based design and best practices - C++

struct InkPen
{
void Write()
{
this->WriteImplementation();
}
void WriteImplementation()
{
std::cout << "Writing using a inkpen" << std::endl;
}
};
struct BoldPen
{
void Write()
{
std::cout << "Writing using a boldpen" << std::endl;
}
};
template<class PenType>
class Writer : public PenType
{
public:
void StartWriting()
{
PenType::Write();
}
};
int main()
{
Writer<InkPen> writer;
writer.StartWriting();
Writer<BoldPen> writer1;
writer1.StartWriting();
return 0;
}
I wrote the above code as part of learning policy based designs. I have few questions on the above code
1 - Does this implementation look correct? I mean: does it really look like a policy based design?
2 - I can now hook any kind of pens to writer. But what will I do when I got a pen with no default constructor (only parameterized constructors)? How will I handle this situation?
template<class PenType>
class Writer : public PenType
{
public:
void StartWriting()
{
PenType::Write();
}
};
3 - When the above code is used like
Writer<InkPen> writer;
I guess compiler will replace PenType with InkPen. If yes, why I am not able to call just Write() from StartWriting() instead of prefixing base class name (PenType::Write())?
4 - I think policy based design forces you to derive from classes which is semantically invalid. In the above code, a writer is derived from a pen only because writer uses a pen. But saying writer is a pen is semantically invalid. Is there any other better way to address this or I am missing something here?
Any thoughts?
Here's how I would implement the class:
template<class PenType>
class Writer
{
public:
Writer(const PenType& pen = PenType()) : pen(pen) {}
void StartWriting()
{
pen.Write();
}
private:
PenType pen;
};
This allows the user to pass a specific Pen object to the constructor, if it either doesn't have a default constructor, or you don't want it to be used, and second, it still allows you to omit the PenType object if you're happy to let it create one with the default constructor. The C++ standard library does the same in many classes (think of the allocators for container classes for example).
I removed the inheritance. It didn't really seem to add anything (and might cause problems. You probably don't want the user of the Writer class to call the PenType::Write function directly. You could use private inheritance instead, but often, composition is a simpler and more conventional design.
In general, policy-based design does not require inheritance. Adding it as a member works just as well. If you do go for inheritance, make it private so you don't get the problem you mentioned as #4.
This looks like a nice example of policy-based smart pointer implementation: link. Andrei Alexandrescu describes policy-based smart pointer implementation in one of his books. As to your questions now. I have some experience in this stuff but not enough to take my words for granted:
Ad 1 & 4. I guess policy-based design is more about templates than inheritance. You write a template class and template arguments are policy classes, like that:
template<class FooPolicy, class BarPolicy>
class Baz {
// implementation goes here
};
Then you use methods from policy classes in your class:
void Baz::someMethod(int someArg) {
FooPolicy::methodInit();
// some stuff
BarPolicy::methodDone();
}
I use static methods in this example because often policy doesn't require any state. If it does, you incorporate policy's state by composition, not by inheritance:
template<class FooPolicy, class BarPolicy>
class Baz {
private:
FooPolicy::State fooState; // might require 'typename' keyword, I didn't
// actually tried this in any compiler
// rest of the Baz class
};
Ad 2. You can write a template specialization - for a particular combination of main class and it's policies you can write a special version of any method or constructor, AFAIK:
template <>
Baz<SomeConcreteFooPolicy, SomeConcreteBazPolicy>::Baz(someArgument)
: fooState(someArgument)
{
// stuff here
}
Hope it helps you a bit,
Mike
I know this thread is old, but there is a major flaw in the initial post and this thread is one of the top results of Google...so:
Do not use public inheritance for policy-based design! This would say "is-a" instead of "has-a" / "uses-a". You should therefore use private inheritance!
1 - Is this implementation looks
correct? I mean is it really looks
like a policy based design?
Policy classes derive their usefulness from combining behaviors to produce a rich variety of combinations. When you have a single template parameter like this, it's not much of a policy class.
2 - I can now hook any kind of pens to
writer. But what will I do when I got
a pen with no default constructor
(only parameterized constructors)? How
will I handle this situation?
Again, this is an odd example of a policy class. However, to directly answer your question, you can provide a constructor which accepts PenType. You should probably also avoid inheriting from PenType and store it as a member instead (no need to tightly couple your policy class with its policies).
I guess compiler will replace PenType
with InkPen. If yes, why I am not able
to call just Write() from
StartWriting() instead of prefixing
base class name (PenType::Write())?
When you inherit from a class template, you have to specify this->member or BaseClass::member.
4 - I think policy based design forces
you to derive from classes which is
semantically invalid. In the above
code, a writer is derived from a pen
only because writer uses a pen. But
saying writer is a pen is semantically
invalid. Is there any other better way
to address this or I am missing
something here?
Store PenType as a member as suggested above. Always prefer composition to inheritance as it avoids the tight coupling relationship of inheritance.