I want to define a structure with different variable type in some field. for example i define a struct like this:
struct sensor {
int index;
int value;
};
struct sensor2 {
int index;
float value;
};
i want to declare only one structure with two option, someone integer value and other time float value, but in unique structure.
My question is :
1.there are anyway to declare one structure and pass parameter to chose one of type (int or float or ...)?
2. can i use template for this reason?
struct sensor {
int index;
type_as_option value; //int or float
};
thank for your aid with best regard
You have several options. You could make it a template:
template <typename T>
struct sensor {
int index;
T value;
};
However, if you want the two structs being the same type, this is not what you are looking for, as
sensor<int>
and
sensor<float>
are two different types.
Second option is (as immibis pointed out in a comment) to simply make a struct with both
struct sensor {
int index;
int ivalue;
float fvalue;
};
However, this introduces almost 50% memory overhead that can be avoided by using a union:
union intOrFloat {
int ivalue;
float fvalue;
};
struct sensor {
int index;
intOrFlaot value;
};
Of the union always only one field is active and it doesnt use more memory than necessary.
Related
I just want to ask if there are any uses for passing variables in cpp as template arguments
template<int a> struct foo {
int x = a;
};
int main() {
foo<2> bar;
std::cout << bar.x;
}
Something like this compiles, works and cout's 2 but the same thing can be done by doing
struct foo {
int x;
foo(int a) : x(a) {}
};
int main() {
foo bar(2);
std::cout << bar.x;
}
So what is the point of using variables in template arguments? I can also see a big flaw in using the first method: the variable a uses memory and isn't destructed after x is changed, as it would be after the constructor is called in the second example. It might be helpful if you showed some reasonable uses for that.
When you pass a variable through a template argument, it can be used in compile time.
For example, if you need to create a statically sized array in your class, you could use the template argument to pass the size of your array:
template <int TSize>
class Foo {
[...] // Do whatever you need to do with mData.
private:
std::array<int, TSize> mData;
};
There are many uses for constants in template parameters.
Static Sizes
This is how you would start implementing something like a std::array.
template <typename T, size_t SIZE>
struct Array {
T data[SIZE];
}
Template parameters are always usable in a constexpr context, so they can be used as sizes for statically sized arrays.
Providing Compile-Time Parameters to Algorithms
Another use is parametrizing algorithms like in the following code sample.
We have a uint32_t in ARGB order but to store it in a file, we might need to reorder it to BGRA or RGBA. We know the order at compile time, so we could use an ArgbOrder template variable.
enum class ArgbOrder { ARGB, RGBA, BGRA };
struct ChannelOffsets {
unsigned a;
unsigned r;
unsigned g;
unsigned b;
};
// and we can get a constexpr lookup table from this enum
constexpr ChannelOffsets byteShiftAmountsOf(ArgbOrder format)
{
...
}
template <ArgbOrder order>
void encodeArgb(uint32_t argb, uint8_t out[4])
{
// We can generate the shift amounts at compile time.
constexpr detail::ChannelOffsets shifts = shiftAmountsOf(order);
out[0] = static_cast<u8>(argb >> shifts.a);
out[1] = static_cast<u8>(argb >> shifts.r);
out[2] = static_cast<u8>(argb >> shifts.g);
out[3] = static_cast<u8>(argb >> shifts.b);
}
void example() {
encodeArgb<ArgbOrder::BGRA>(12345);
}
In this example, we can select the appropriate lookup table at compile time and have zero runtime cost. All that needs to happen at runtime is 4 shifts.
Feature Toggles
We can use bool template variables to toggle features in our code, like for example:
template <bool handleZeroSpecially>
int div(int x, int y) {
if constexpr (handleZeroSpecially) {
return y == 0 ? 0 : x / y;
}
else {
return x / y;
}
}
I'd need to modify a simple struct to accept multiple types of value parameters, as shown below:
struct menuitems_t
{
menuitems_t(std::string name, float* value = 0, int itemtype = menuitemtype::SWITCH)
{
this->name = name;
this->value = value;
this->itemtype = itemtype;
}
std::string name;
float* value;
int itemtype;
};
I tried to create a template from it, but with no luck.
declaring one of these is like menuitems_t(nameString, val1, type);
My only problem is that if I want to use a bool as the referenced value it won't accept it obviously. (I can cast it as a float, but that's not what I want.)
What should I modify in it to accept any types?
You could use a void*, but that's a very C-style and type-unsafe solution to the problem.
Any other pointer can be converted to a void-pointer implicitly, but you need to keep track of the type yourself.
struct menuitems_t
{
std::string name;
void* value;
int itemtype;
};
void foo() {
menuitems_t myItems{"name", nullptr, 0};
// ...
}
On a side note, you don't need a custom constructor and can just use aggregate-initialization.
And it's better practice to use nullptr instead of 0.
Using templates would be more type-safe, but you need to keep track of types at compile-time.
template <typename T>
struct menuitems_t
{
std::string name;
T value; // or T* value if it's still supposed to be a pointer
int itemtype;
};
If there can only be a limited amount of types, you can use a std::variant. You could also just use a union, but unions don't have runtime type-safety like std::variant.
struct menuitems_t
{
std::string name;
std::variant<float, bool> value;
int itemtype;
};
I am stuck in a situation please help me out of this.
Thought:
To have a common Interface among different Detection algorithms(Say Circle, Triangle and Rectangle).
class IDetectionInterface()
{
public:
virtual void PerformDetection(Image & InputImage, DetectionStruct & DetectionData, DetectionParam & DetParam) = 0;
virtual ~IDetectionInterface()
{
}
};
where Image and DetectionStruct is a structure as below:
struct Image
{
unsigned char * pImageData;
int Width;
int Height;
};
struct DetectionStruct
{
Rect BoundingBox;
DectionType DetType;
};
struct Rect
{
int x;
int y;
int width;
int height;
};
enum DectionType
{
Circle = 0,
Triangle = 1,
Rectangle = 2
}
The Problem for me is that of DetectionParam, as Parameters of Detection Algorithms differ. Say for example
struct RectDetectionParam
{
int param1;
float param2;
double param3;
};
struct TriDetectionParam
{
float param1;
float param2;
double param3;
int param4;
};
struct CirDetectionParam
{
int param1;
float param2;
bool param3;
int param4;
float param5;
};
How can i get this to common interface as above.
Note: I don't want to put all the parameters in one structure which is a easiest solution, But it has its drawback if i change the algorithm then its respective parameters changes and we need to re write the structure again.
And Ofcource Yes, I will have the implementation of the interface(Abstract class)
Thanks in advance
Based on your example you could create a discriminated union to make the parameter sets generic:
struct DetectionParams {
DectionType detectionType; // Discriminator
union {
RectDetectionParam rectDect;
TriDetectionParam triDect;
CirDetectionParam cirDect;
};
};
Which of the union parts is used in the implementation is determined by the discriminator.
Another way is to use something like a parameter set based on unique parameter names (key strings):
struct DetectionParams {
std::map<std::string,std::any> params; // Note that std::any is available
// at the not yet official c++17 standard
};
If I have:
typedef struct Foo {
int x, y;
} Point, SomethingElse;
and I want Foo.x to equal Point.x but I want SomethingElse.a to also be equal to Point.x or in other words, I want SomethingElse to be the exact same as Foo and Point but with its two variables named other things. It would seem like a waste if I have to make a whole new struct.
If enforcing the different variable names for the different types isn't a requirement, what about using unions?
typedef struct Foo
{
union
{
int a;
int x;
};
union
{
int b;
int y;
};
} Point, SomethingElse;
You could instead treat the variables as an array within the object and use the array operator to retrieve the values using variables with the names you desire.
struct example{
int data[2];
int& operator[](int index){
//range check index before lookup if desired
return data[index];
}
};
int X=0;
int Y=1;
int A=0;
int B=1;
typedef example Point;
typedef example SomethingElse;
int main(int argc,char** argv){
Point p;
SomethingElse s;
p[X]=0;
s[A]=0;
return 0;
}
This is one way you could do something like what you are requesting, but I would suggest either declaring unique structs with the names you desire in each one rather than trying to provide aliases to names of variables within a struct. It seems like much less of a headache to just declare a second struct.
You have 3 different typdefs which are identiacal structs declared in one statment. SomethingElse doesn't have a member named a.
Also maybe you wanted a typedef union?
I have a function to compute gradient of different variable defined on set of neighbor points. The algorithm is always the same, but depending on what is computed, different member data of the neighbors are accessed, e.g. when computing gradient of velocity, use Node::velocity, when computing gradient of stress, use Node::stress. What is the best way to avoid writing the same function several times?
I had several possibilities in mind:
Pass lambda function (c++0x)
or callable object returning that particular member data in question, called like
gradVelocity=computeGradient(listOfNeighbors,[](const Node& n){ return n.velocity; });
The minus is extra function call at every read.
Template the function based on integer saying what is being computed:
enum{VAL_VELOCITY=0,VAL_STRESS,VAL_SOMETHING};
template<int what> computeGradient(const std::list<Node>& neighbors){
/*loop over neighbors*/
value=(what==VAL_VELOCITY?neighbor.velocity:((what==VAL_STRESS)?neighbor.stress:neighbor.something);
/* and so on */
}
/* called like this */
gradVelocity=computeGradient<VAL_VELOCITY>(neighbors);
It should be perhaps efficient (hoping compiler will optimize the conditional with constants away in individual instantiations), but readability and maintainability is pretty low.
Some better idea?
If all of your fields have the same types, it's easy to use pointers to members:
struct Node
{
double stress;
double velosity;
};
void foo(Node* pNode, double Node::*pValue)
{
cout << pNode->*pValue << endl;
}
int main()
{
Node n1 = { 1, 2 };
foo(&n1, &Node::stress);
foo(&n1, &Node::velosity);
}
Update: If not, it's still easy to combine pointers to members with templates:
struct Node
{
double stress;
double velosity;
int dimension;
};
template<class T>
void foo(Node* pNode, T Node::*pValue)
{
cout << pNode->*pValue << endl;
}
int main()
{
Node n1 = { 1, 2 };
foo(&n1, &Node::stress);
foo(&n1, &Node::velosity);
foo(&n1, &Node::dimension);
}
I think this is probably the most efficient possible way. It's pretty vivid too.
Pointer to member is what you need. The type is written as T S::* T is the type of the data member, S is your struct or class. Here is a small example:
#include <iostream>
struct Foo
{
int a;
double b;
Foo(int a, double b)
: a(a), b(b)
{ }
};
template<typename T, T Foo::* mem>
void print(const Foo& foo)
{
std::cout << foo.*mem << std::endl;
}
int main()
{
Foo f(5, 3.14);
print<int, &Foo::a>(f);
print<double, &Foo::b>(f);
}
I am a huge fan of Boost.Fusion, and more specifically, the Boost.Fusion.Map, which let you build a type -> value kind of map.
struct Velocity {};
struct Stress {};
typedef boost::fusion::map<
std::pair<Velocity, double>,
std::pair<Stress, int>
> Map;
Map map;
Now, you can access the map with types:
boost::fusion::at_key<Velocity>(map)
returns a reference to a variable of type boost::fusion::result_of::at_key<Velocity, Map>::type
With appropriate wrapping, you get:
extern Velocity const velocity;
extern Stress const stress;
myItem.access(stress) = 3;
And of course, since we are talking templates, no runtime penalty, at all :)
What about inheriting from Node and using virtual access? It would even be possible to use CRTP to avoid the virtual call.
You can combine velocity, stress, something in a single array and access them based on enum index.
struct Node
{
int attributes[3]; // contains 'velocity', 'stress', 'something';
enum { VAL_VELOCITY=0, VAL_STRESS, VAL_SOMETHING };
};
Usage:
Node n;
n.attributes[Node::VAL_VELOCITY] = <value>; // writing 'Node::velocity'
<otherthing> = n.attributes[Node::VAL_SOMETHING]; // reading 'Node::something'
[Note: If you want to keep attributes inside private region then provide getter and setter methods in Node for accessing them.]