golang Define struct once and use it in another struct definition - go

Define struct once and use it in another struct defination
type FormAction struct {
Data bool `yaml:"data,omitempty" json:"data,omitempty"`
Self bool `yaml:"self,omitempty" json:"self,omitempty"`
Blob bool `yaml:"blob,omitempty" json:"blob,omitempty"`
}
type ManifestSrc struct {
Data bool `yaml:"data,omitempty" json:"data,omitempty"`
Self bool `yaml:"self,omitempty" json:"self,omitempty"`
Blob bool `yaml:"blob,omitempty" json:"blob,omitempty"`
}
type PrefetchSrc struct {
Data bool `yaml:"data,omitempty" json:"data,omitempty"`
Self bool `yaml:"self,omitempty" json:"self,omitempty"`
Blob bool `yaml:"blob,omitempty" json:"blob,omitempty"`
}
how we can reduce the redundancy of same members ?

Probably the most idiomatic way of defining the same fields in multiple structs without repeating yourself is to use embedding, because it still allows you to add other fields, eg:
type entity struct {
Data bool `yaml:"data,omitempty" json:"data,omitempty"`
Self bool `yaml:"self,omitempty" json:"self,omitempty"`
Blob bool `yaml:"blob,omitempty" json:"blob,omitempty"`
}
type FormAction struct {
entity
}
type ManifestSrc struct {
entity
}
type PrefetchSrc struct {
entity
AnotherField string // For example
}

Related

Conditional ref qualifier

I have CRTP-like hierarchy where derived classes may be implemented a bit differently and for one class some methods are allowed to call on rvalue references but for another class this would be undesired:
template <class TDerived>
struct Base {
TDerived& foo() {
// Body
return static_cast<TDerived&>(*this);
}
};
struct Derived1: public Base<Derived1> {};
struct Derived2: public Base<Derived2> {};
int main() {
// Should not compile:
// Derived1().foo();
// Should compile:
Derived2().foo();
return 0;
}
So to prohibit calling foo() on rvalue references one can add ref-qualifier like this:
TDerived& foo() & {...}
But I'm wondering is there any simple way to add such ref-qualifier conditionally without duplicating foo() method (and adding a bit of SFINAE-like code)?

Shared_Ptr<Derived> being upcast to Shared_Ptr<Base>

I am trying to attach bits of data, called components, to an Entity node.
However, whenever I attach a derived component type to the Entity node, it is being upcasted to the base Component type instead of staying a child. How could I prevent this so I can make use of std::type_index?
Currently, because the Component is being upcasted, std::type_index keeps making an index for Component, rather than one of the child classes. Do I have to template out the AttachComponent method? I'd rather not.
class Entity final
{
//Typedefs
typedef std::map<std::type_index, std::shared_ptr<acorn::Component> > ComponentMap;
ComponentMap m_components;
unsigned long int m_ID;
private:
public:
explicit Entity(unsigned long int id);
~Entity();
//Getters
inline unsigned long int GetID() const
{
return m_ID;
}
template<class ComponentType>
std::weak_ptr<ComponentType> GetComponent()
{
auto component_map_it = m_components.find(std::type_index(typeid(ComponentType)));
//If the component was found
if (component_map_it != m_components.end()) {
//Get the shared_ptr of the component
std::shared_ptr<acorn::Component> base_ptr = component_map_it->second;
//Cast it to the desired component type
std::shared_ptr<ComponentType> converted_ptr(std::static_pointer_cast<ComponentType>(base_ptr));
//Convert to a weak pointer
std::weak_ptr<ComponentType> return_ptr(converted_ptr);
//Return the weak pointer
return return_ptr;
}
else {
//If no component type was found, return a nullptr.
return std::weak_ptr<ComponentType>();
}
}
//Setters
inline void AttachComponent(std::shared_ptr<Component> component)
{
auto raw_ptr = component.get();
auto insert_pair = std::make_pair(std::type_index(typeid(raw_ptr)), component);
m_components.insert(insert_pair);
}
};`
Yes, you have to make AttachComponent a template. That's the only way to preserve the type information:
template <class T>
void AttachComponent(std::shared_ptr<T> component)
{
// as before
}

Call to derived class function in vector populated with variadic initializer list doesn’t behave polymorphically

I am using an initializer list to declare an arbitrary number of item pairs at compile time, each consisting of a key and a real type as the value. There are two derived real types in the model code: MyA and MyB, both of which derive from My. The vector gets initialized with a key and a particular derived type like, {33, MyA}. I insert this set of initializations into a vector using std::initializer_list. The MyA and MyB constructors get properly called so I know the correct objects are getting constructed.
Being able to declare/instantiate an arbitrary number of item pairs at compile time will greatly reduce the complexity of my prototype code by eliminating much redundant code and allowing me to easily add additional sets of pairs as the code matures. itemVect1 in the model code works fine.
But when I make a call on MyAFunc(), itemVect1 executes the base class’s MyFunc().
Is there a way I can use this very powerful variadic code machinery and still maintain polymorphic access to various derived types which I want to pass in in the initializer list?
I built my model code off of the code in StackOverflow “Inserting a variadic argument list into a vector?”
struct My
{
My() {}
void MyFunc() {}
virtual void MyAFunc() {}
virtual void MyBFunc() {}
};
struct MyA : My
{
MyA() : My() {}
void MyAFunc() {}
};
struct MyB : My
{
MyB() : My() {}
void MyBFunc() {}
};
template< typename KeyT, typename ValueT >
struct ItemPair
{
ItemPair( KeyT key, ValueT val )
: key( key ), val( val ) {}
KeyT key;
ValueT val;
};
typedef ItemPair< const int, My > IPIntMy;
struct ItemPairVect
{
ItemPairVect( std::initializer_list< IPIntMy > initList )
: ipVect( initList ) {}
std::vector< IPIntMy > ipVect;
};
int main()
{
ItemPairVect itemVect1 { IPIntMy { 33, MyA {} }, IPIntMy { 44, MyB {} }, IPIntMy { 55, MyA {} }, IPIntMy { 66, MyB {} } }; // works fine
itemVect1.ipVect[ 0 ].val.MyAFunc(); // doesn't behave polymorphically, that is, it calls MyFunc() instead
}
I tried changing My to My* in the typedef which is the normal way to make an object polymorphic, but had problems getting the initializer list to parse.

C++11 variadic template parameter expansion

I would like to do the following:
template<typename Func>
class FunctionWrapper
{
public:
typedef decltype(Func()) ReturnType;
typedef ... ArgsType;
FunctionWrapper(Func func)
{
func_ = func;
}
ReturnType operator() (ArgsType args)
{
return func_(args);
}
private:
Func func_;
};
The problem is I don't know how to deduce the ArgsType from Func type. I'd like to make it work when the function returns/accepts nothing as well.
The usecase would then be:
FunctionWrapper<myFunction> wrapper;
auto result = wrapper(1, 2, 3);
You can determine the argument and return type(s) in operator() and use perfect forwarding:
template <typename Func>
class FunctionWrapper
{
Func func_;
public:
FunctionWrapper(Func func) : func_(func) {}
template <typename... Args>
auto operator() (Args&&... args)
-> decltype(func_(std::forward<Args>(args)...)) {
return func_(std::forward<Args>(args)...);
}
};
There is no generic way to do that, neither is it logical. Just think of the case when Func overloads operator() and accepts different argument types. You could, however, mandates that Func defines its argument type as a member type for utility like FunctionWrapper to access. See the possible member types of std::function for an example.

Groups inside structs

Can I have groups inside a struct?
pseudo-code:
typedef struct {
input_group {
logic a;
}
output_group {
logic b;
}
} my_signals_list
Short answer: no.
If you want to have signals grouped like this, why not create a struct for the input group and a struct for your output group?
typedef struct {
logic a;
} input_group_s;
typedef struct {
logic b;
} output_group_s;
typedef struct {
input_group_s input_group;
output_group_s output_group;
} my_signals_list;
As Greg points out in the comments, you can also have nested struct definitions inside the main struct:
typedef struct {
struct { logic a; } input_group;
struct { logic b; } output_group;
} my_signals_list;
If you want to specify signals for a module in a nice encapsulated fashion, I would suggest using an interface, though.

Resources