Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
158 views
in Technique[技术] by (71.8m points)

c++ - Generically accessing data from a varying list of attributes within sub-classes while maintaining polymorphic behavior

With the use of constant expressions, parameter packs, lambdas, move semantics, standard containers, and std::any I can easily enough create the following design pattern:

#include <utility>
#include <vector>
#include <any>

constexpr auto assign_properties = [](auto&&... t) { 
    return std::vector<std::any>{ std::move(t)... };  
};  

That would create an arbitrary list of properties or attributes without the need of defining a struct or class object.

Simply enough it can be used in the following manner:

{
     auto props = assign_properties(1, 3.1f, 6.4, 'a');
}

Now, to access the type-safe data within this container one would have to know each element's type in advance and would have to extract them in the following manner:

{
    auto a = std::any_cast<int>( props[0] );
    auto b = std::any_cast<float>( props[1] );
    auto c = std::any_cast<double>( props[2] );
    auto d = std::any_cast<char>( props[3] );
}

Okay, this is simple and fair enough...

Let's say I want to incorporate some kind of mechanism such as this within a class hierarchy that will preserve polymorphic behaviors...

Within the class hierarchy, I may want to have an abstract base type that all types are derived from. As for each derived or subclass, they may contain a set of properties or attributes that describes either its behavior or state, however, each subclass may have a different amount of attributes with various different types...

For example:

class Animal {
protected:
    Animal(); // Abstract
    std::vector<std::any> attributes_;
};
     
class Cat : public Animal {  
public:
    // ...    
};

class Dog : public Animal {
public:
   // ...
};

class Eagle : public Animal {
public:
   // ...
};

Now, I'm not showing any polymorphic behavior, virtual, or purely virtual methods here since they are not necessary towards the intent of my question which I will get to briefly... somewhere else within some other code these objects are being created and then populated...

struct Fur;    
struct Fangs;
struct Claws;
struct Feathers;
struct Talons;
struct Scales;

{
   Cat c1;
   c1.populate_attributes(assign_properties( "Fluffy", 9, Fur, Fangs, Claws));

   Dog d1;
   d1.populate_attributes(assign_properties( "Ruff", 3, Fur, Fangs, Claws ));
   
   Eagle e1;
   e1.populate_attriutes(assign_properties( Fangs, Claws, Feathers, Talons );
}

Simple enough... Now, as I stated above, accessing the values within these vectors from std::any requires you to know the type ahead of time in order to use std::any_cast to extract its value in a type-safe manner.

Let's say that I plan on using this while parsing a file to create and populate my class data types with their properties. Then somewhere else in some other function or code block, these elements need to be accessed and I don't know what their types are... std::any within this context does not provide any facilities nor helps me with this process.

{ 
    std::vector<Animals*> animals { Constructed & Populated; }
}
// some other code block
{
    auto a, b, c, d, ...;
    a = animals[0];
    b = animals[1];
    c = animals[2];
    d = animals[3];
    
    // Above we got each individual animal from our external source vector...
    
    auto e,f,g,h, ...;
    e = a[0]; // doesn't give the type and its value, e will be `std::any`.
    e = std::any_cast<auto>( e[0] ); // will fail to compile since `<T>` must
                                     // be known at compile time.
    e = std::any_cast<?>( e[0] );    // ... and this is where I'm stuck
                                     // I need some form of extraction here!
                                     // and I would like for it to be automatic and generic.
}        

If the user doesn't know the types ahead of time and needs to access these values within a type-safe context, is there an easy way to automate this retrieval or extraction process with the current implementation that is described above? If not, what can be done to modify the above code to make it work as intended, or is there any other mechanism or construct that could be used in place of this to implement a similar design pattern while preserving or providing the behavior that I have expressed?

question from:https://stackoverflow.com/questions/65940503/generically-accessing-data-from-a-varying-list-of-attributes-within-sub-classes

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...