So I'm trying to nest a struct into another one by value, but I want to be able to import the members of the nested structs as if they are direct members of Generic struct. There seems to be a using keywork in C++, but it doesn't work as I would have expected.
For example:
struct A
{
int a;
// some specific A stuff
};
struct B
{
float a;
// some specific B stuff
};
template<typename T>
struct Generic
{
Kind kind; // an enum or an integer ID that allow to figure out what type is contained
// some generic stuff
// how to do this?
using T t; // Error: a class-qualified name is required
// some more generic stuff
};
void foo()
{
Generic<B> g;
g.t.a = 6.7 // we can do this with regular struct field
g.a = 5.4; // but need to be able to do this
}
This construct is made in this way to be able to create different user-extensible views into some differently-sized item buffer, where each item is a tagged union with custom contents and common header and footer.
So the main question: How to import ("use") some struct into a different one and be able to access the nested struct' fields directly?
There is a possible way to work around the problem by using inheritance, but it needs more structures:
// The "data" structures
struct A { ... };
struct B { ... };
// Common "header" structure
struct Header { ... };
// The "generic" structure to combine the header with the data
template<typename D>
struct Data : Header, D
{
// Empty
};
Now you can use the B data as
Data<B> data;
The header information will come first, the actual data follow. And the size will depend on the data structure.
But please note that from a design point of view, this is highly dubious. I would prefer actual composition:
struct A
{
// Actual A data fields follow
};
struct Data_A
{
Header header;
A data;
};
This allows you to read the header and data separately from the buffer. It's also more explicit about the separation of the header and the data, and should make the code clearer and easier to read, understand and maintain.
Related
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.
I wonder if it is possible to generate types set from enum class for the metaprogramming purposes.
I'm originally a C# programmer and used to using a lot of attributes for reflection and metaprogramming. For example, it is a general pattern for me to write a snippet like that with C#:
public enum ComponentEnum { Component1, Component2, Component3 }
[Component(ComponentEnum.Component1)]
public class Component1
{
/* Some code */
}
public static class ComponentsMeta
{
private static Dictionary<Type, ComponentEnum> map;
static ComponentMeta() { /*process the whole codebase via reflection, search Component marked classes an fill the map */}
public static bool IsComponent<T>() => map.ContainsKey(typeof(T));
public static int GetComponentUID<T>() => (int)map[typeof(T)];
}
Of course, it is a very basic snippet without asserts and some other stuff but I believe you got the idea.
I want to make the same behavior in the c++ snippet. What I want to do exactly is makes a type called Components that will contain some utility functions like bool Components::isComponent<T>() or size_t Components::getComponentUID<T>() or some related stuff. The best way I've seen so far is to write it down by myself, making a metaclass like
template <typename Ts..>
class ComponentsData
{
/* functions impl here */
}
typedef ComponentsData<C1, C2, C3> Components;
So, now I can ask Components<C1>::getComponentUID() and it returns me uid of that component (depends on its position as template parameter or constexpr value of that component, it doesn't matter). But it is a very inconvenient way to do that and I wonder if I can put a macro inside the component class or using attributes and code generation step or something. In other words, my goal is to mark somehow the class that it should be in that components set and use it later. What c++ can offer for that purpose?
It will be okay if I could make something like I did C# way - make an enum class, list all the components there, and write a constexpr value inside a component class (or somewhere near the enum class, both ways is good for me).
I mean something like that:
/* ComponentsEnum.h */
enum class ComponentsEnum { Comp1, Comp2, Comp3 };
// Here is some magic to generate Components<C1, C2, C3> metaclass.
/* another file */
#include "ComponentsEnum.h"
struct C1 { const ComponentsEnum MyValue = ComponentsEnum::Comp1; };
or something like that
/* ComponentsEnum.h */
enum class ComponentsEnum { Comp1, Comp2, Comp3 };
// Here is all the magic
// All enum members concats into `Components<Comp1, Comp2, Comp3, ...>`
ConcatAll<ComponentsEnum>();
/* another file */
#include "ComponentsEnum.h"
struct Comp1 { };
or maybe something with macro magic:
/* ComponentsEnum.h */
enum class ComponentsEnum { Comp1, Comp2, Comp3 };
#define InitMeta(ComponentsEnumMember) /* Some Magic */
/* another file */
#include "ComponentsEnum.h"
struct Comp1 { InitMeta(ComponentsEnum::Comp1) };
Thanks in advance!
Following on my comment.
You could do something like this in C++17:
// In register.hpp
int register_me();
// In register.cpp
int register_me(){
static int id = 0;
return id++;
}
// In wherever.hpp
// #include "register.hpp"
struct component{
inline static int id = register_me();
};
Pre-C++17 requires moving the definition and initialization to a .cpp for each component::id.
But I strongly recommend not to use this. Rethink your design, converting types to IDs is a code smell for me. C++ is not really designed to do such things, it can haunt you later.
The code above relies on dynamic initialization of all static variable at the start of the program. The order is unspecified, each compilation might result in assignment of different IDs.
Definitely do not put this into any shared libraries before being 100% sure you know how the compilation, linking, and loading processes work for your toolchain because these are outside the scope of C++ Standard.
Thanks to the #JerryJeremiah link and #Quimby advice, I found the solution.
So, I was misled by my C# habits and the idea was quite simple but tricky.
According to the difference between C# generics and C++ templates, generics are runtime instanced types, but templates are compile-time types. So, I do not need to create a map or process the whole codebase, all I need will be generated with templates in compile time.
The solution itself:
I want an enum to generate continuous uid numbers for my components. So, define it:
enum class ComponentEnum
{
C1,
C2,
C3
};
I want a simple interface for my Components to ask for meta information. Define it too:
struct Components
{
template<typename T>
static bool isComponent() { /* Some stuff here */ }
template<typename T>
static int getComponentUID() { /* Some stuff here */ }
};
Now I can ask uid with one simple generalized call Components::getComponentUID<MyComponent>(). Nice.
The real magic. I've created template metaclass and macro to create a typedef and some additional methods:
template <typename T, ComponentEnum enumMember>
struct ComponentMeta
{
static constexpr bool isComponent = true;
static constexpr int uid = static_cast<int>(enumMember);
};
#define ComponentMetaMacro(type_name, enum_name) typedef ComponentMeta<type_name, ComponentEnum::enum_name> Meta; \
static const char* toString() { return #type_name; }
So I can fill methods from my interface with simple forwarding to that metaclass:
struct Components
{
template<typename T>
static bool isComponent() { return T::Meta::isComponent; }
template<typename T>
static int getComponentUID() { return T::Meta::uid; }
};
All things left is include header with metaclass and macro and call the macro:
struct C1
{
ComponentMetaMacro(C1, C1)
};
struct C2
{
ComponentMetaMacro(C2, C2)
};
Run a few tests:
std::cout << C1::toString() << ": " << Components::getComponentUID<C1>() << std::endl;
std::cout << C2::toString() << ": " << Components::getComponentUID<C2>() << std::endl;
C1: 0
C2: 1
Yay!
This solution has three main problems:
isComponent() becomes the static assert instead of the flag. I mean, the code won't compile if T-type is not a component. It is quite ok but smells.
It is a single linked meta. I can't get a component type from the index, only an index from the type. But for serialization purposes, it could be useful to have a backlink.
I should include the enum class to every component header. It means there will be a huge compile-time affect when I will add a new enum member. I suppose there is a way to avoid it but can't see one. The only enum class purpose is to have the smallest index as possible for every component that will be static between compilations. Maybe I have to think about some data generation or another approaches, but for the small project it is ok.
I have this code right now, which seems to work so far but I was wondering if there was a way to get the exact same struct in a more elegant way since my method so far needs a duplicate everytime for each struct... The end goal would be to have a typedefed struct which would swap the bytes according to the endianness automatically.
using ResourceHeader_t = struct ResourceHeader_s
{
uint32_t magic;
uint32_t chunkVersion;
uint32_t chunkSize;
};
template<bool bigEndian>
struct ResourceHeader : public ResourceHeader_s
{
ResourceHeader(ResourceHeader_t* ptr) : ResourceHeader_s(*ptr)
{
if (bigEndian)
{
LITTLE_BIG_SWAP(magic);
LITTLE_BIG_SWAP(chunkVersion);
LITTLE_BIG_SWAP(chunkSize);
}
}
};
Usage example :
ResourceHeader<true> resourceHeader((ResourceHeader_t *)fileBuffer);
There is no need for a typedef struct declaration in C++. This is a relic of C.
In C++, after declaring a struct ResourceHeader_s, or struct ResourceHeader_t, or just a plain struct ResourceHeader, the same symbol can be used directly by itself, without an explicit struct.
You might simply add the endianess as a ResourceHeader ctor parameter, rather than a template parameter. This would remove duplicate definitions of the struct (one for big and one not).
I have the following situation. We are writing a library which has a class which has a lot of fields (majority) of it depending on some optional fields which have "flags" (bits in a number basically) if the optional field is present or not.
The fields of the class are required to be public for easier access (I know it's bad), and 3rd party developers will read the header files (beside of their documentation) in order to get familiar with the structure and the connection of various fields to their corresponding options.
The problem is, the customer wants to make easy for their developers to identify which fields depends on which optional structure with as little effort as possible.
One of the solutions is to put a comment above or after the field (class member) name telling it uses this option field. This is the basic choice.
However the class is already over populated with around 500 members (fields) so I don't know that if adding extra 500 lines, or long comments will add to the quality of it.
We came up with the following constructs:
#define DEPENDS
#define ON
#define BIT(x) ((x)-1)
#define OF(x)
struct source{};
struct options
{
options(const source&) {}
};
template <int BITIDX>
struct optional
{
optional(const options&) {}
};
struct something
{
// this constructor will be implemented in the CPP
// so the user (developer) will not see it
something (const source& src) :
msource(src), initial_options(src), other_options(src),
field1(initial_options), field2(other_options) {}
options initial_options;
options other_options;
optional<DEPENDS ON BIT(1) OF (initial_options)> field1;
optional<DEPENDS ON BIT(1) OF (other_options) > field2;
source msource;
};
int main()
{
source s;
something a(s);
}
but obviously this is not much better due to namespace pollution, macros, etc ...
So, the question: is there a better way to achieve our goal to provide a meaningful way of presenting the connection of a field from a bit of an option?
(Please note, C++11 class member initialization is NOT allowed, otherwise I would not ask this question :) We have to stick to older compilers :( )
struct something
{
enum OptionGroup { Initial, Other /*...*/ };
enum InitialFields { A, B /*...*/ };
enum OtherFields { X, Y /*...*/ };
So, we enumerated the fields A,B etc. inside each optional group. Since they're zero-based and incrementing, the enumerated values will tell us which bit represents each field.
template <typename TYPE, OptionGroup GROUP, int BIT>
struct Optional {
TYPE val;
operator TYPE& () { return val; }
operator TYPE const& () const { return val; }
};
This records the group of an optional field, and which bit within that group represents it. You didn't say what the type of your fields is, so I made it generic. You also didn't say how you initialize them, so it might need constructors etc.
int mandatory1;
int initialOptions;
Optional<int, Initial, A> a;
Optional<int, Initial, B> b;
int otherOptions;
Optional<double, Other, X> x;
And here we have the actual storage for a sequence of mandatory and optional fields.
now, we need some way to get the flags for each group:
template <OptionGroup GROUP> int getGroupFlags();
with that, we can check whether a given field is valid ...
template <typename TYPE, OptionGroup GROUP, int BIT>
bool isValid(Optional<TYPE,GROUP,BIT> const &field) {
return getGroupFlags<GROUP>() & (1 << BIT);
}
};
Sadly, recording the association between the enumeration and the group is still manual (this is where being able to merge both sets of option flags into a single bit field would have made life easier)
template <> int something::getGroupFlags<something::Initial>() { return intialOptions; }
template <> int something::getGroupFlags<something::Other>() { return otherOptions; }
This could be cleaned up considerably (eg, by binding each optional group into a single struct instead of hard-coding the nasty OptionGroup->flag field relationship), but this seems like the least work.
hello every i have made a structure and i want to make 2 objects of it . i am using qtcreator.
i write
struct grapharray gao ; (grapharray is my structure)
every thig works well but when i write another object like
struct grapharray gao ;
struct grapharray gao1 ;
my program unexpectedly finishes can any one tell me why is it so and where should i declare the struct object
struct grapharray
{
int structcol;
double *structpayloadgraph;
double *structsessiongraph;
};
here is my structure;
and i have a function
struct grapharray graphplotdata(char * filename)
{ // computing some values and returning structure object
}
thanks
If I understand well the problem, I would say that you use far too much the "struct" keyword.
If you define your struct as
struct grapharray
{
int structcol;
double *structpayloadgraph;
double *structsessiongraph;
};
then you don't need to use the keyword "struct" when declaring the variables.
grapharray gao; // without struct keyword
grapharray gao1; // without struct keyword
and your function should be
grapharray graphplotdata(char * filename) // without struct once again.
{
// computing some values and returning structure object
}
structs does works almost the same way as classes; the main difference is that structs members and methods are "public" by default and classes members and methods are "private" by default.
Edit: Considering the comment of Dennis Zickefoose, this is not the good answer.