What are some good techniques for getting class name in C++? - c++

I'm NOT talking about typeid, I'm just looking for general method to bind a single object (e.g. std::string like in my case) to objects of some class and make its getter polymorphic or something. I can't really give a proper definition so i think that it's just like the problem of getting a class name but you set it yourself somewhere and the only problems are where do you set it and how do you return it.
I'm just gonna give a few examples that do what I want but aren't really as efficient as I want them to be.
virtual string GetClassName() const { return string("MyClass"); } - consumes extra time to build and copy a string every time it is called
const string& GetClassName() const { return class_name_; } where class_name_ is a protected class field that is set in the constructor - the same string is stored in every object, thus it is not memory-efficient
I'm thinking about something like returning a const reference to a static object, but I can't really find a way to make it polymorphic.
Any ideas?

You don't need to reinvent the wheel, when you can just extend it with the right tire.
The C++standard gives you typeid() that works in all the the cases, including built-in types, custom classes, polymorphic classes, multiple inheritance, virtual inheritance and things like that.
Now you may not like the names used by typeid(), which are implementation specific. Or you may want to extend the information available with your own type management extensions. In this case, Bjarne Stroustrup proposed in "The design and evolution of C++" a very simple and effective solution.
The typeid() returns a reference to a const std::type_info. Now you can use the address of this object in a unordered_map, to map the type to your own custom information that could provide the name you want.
The advantage of this solution: uses robust built-in capability, is based on a single additional object per class (could be static), very low overhead to get to the name. all you need to do is to think about how to best populate the map.
Here a small and quick proof of concept (must be improved of course):
// Basic principle of the idea
map<const type_info*, string> mytypes;
template <class T>
const string& mytype(T &&x) {
return mytypes[&typeid(x)];
}
// Some test types
struct A { virtual int test() {} };
struct B : A {};
int main() {
// To be improved: initialization of the type info extension
mytypes[&typeid(int)]="Plain C++ integer";
mytypes[&typeid(A)]="Structure A";
mytypes[&typeid(B)]="Structure B";
// demo, including polymorphic type
int a;
A * p = new B;
cout << typeid(int).name() <<endl;
cout << mytype(a) <<endl;
cout << mytype(*p) <<endl;
return 0;
}
Online demo

What I think you want is some base NamedClass with a virtual std::string_view getName() const that returns the name of the derived class. So you want something like typeid(object).name() but without the name mangling.
Every class that derives from NamedClass should override getName and return the class name.
class NamedClass {
public:
virtual std::string_view getName() const = 0;
};
class Derived final : public NamedClass {
public:
std::string_view getName() const override {
return "Derived";
}
};
If you hate this duplication as much as I do, you could use a macro.
#define GET_NAME(NAME) \
std::string_view getName() const override { return #NAME; }
class Derived final : public NamedClass {
public:
GET_NAME(Derived)
};
I highly recommend using a std::string_view instead of a const std::string & if all you want to do is "view" the string.

Related

Accessing a virtual member function of a template argument derived class in C++

I might simply be overlooking something or being stupid, in which case I am sorry, but I'm really not sure how to, if it is even possible, access a virtual member function. Actually, the virtual part is a second issue about a possible solution I will describe later. Here's some example code that summarizes my issue:
class BaseClass
{
public:
virtual std::string ClassName()
{
return "BaseClass";
}
};
class DerivedClass : public BaseClass
{
public:
std::string ClassName()
{
return "DerivedClass";
}
};
template<class cT>
void StatusPrint(const std::string& message)
{
return cT.ClassName(); // Here's where my issue arises.
}
So, I tried to replace cT. with ct::, however, while that causes compiler issues on its own, it also tries to access the virtual function in BaseClass, but I want to access the overridden function in DerivedClass.
Is what I am trying to do possible like this?
Sorry if I'd seem rude, but you cannot return anything from void function. So apparently, we don't have the full story here.
Do you really want a compile time solution?
Looking at your code, it seems that className() does not use at all the state of the object. So you could make it static (instead of virtual). THe problem would then be solved with:
template<class cT>
std::string StatusPrint(const std::string& message) // returns string, not void
{
return cT::ClassName(); // :: if class name is static.
}
Since the template cannot derive the type from its argument, you'd need to provide it, making the choice of the class completely compile-time:
cout<< StatusPrint<DerivedClass>("test"s)<<endl;
This kind of practice is used, when you have some utility classes and you want to configure at compile time which one to use.
Do you want a dynamic solution?
If you want a dynamic solution at runtime, you need to use some object, because virtual require an object that knows its dynamic type at runtime.
Then it depends on the context. One solution is to use a cT parameter, with the advantage of parameter deduction:
template<class cT>
std::string StatusPrint ( cT object, const std::string& message)
{
return object.ClassName(); // Here's where my issue arises.
}
You'd then call it:
DerivedClass test;
...
cout<< StatusPrint(test, "test"s)<<endl;
Online Demo
But of course, it could also use some global object instead (but the template makes then much less sense), or better, an object in a template class if you refactor StatusPrint() to be a member function of such a class.
I'm not sure what exactly you are trying to do, but see if this is more like it:
std::string StatusPrint(BaseClass *instance) {
return instance->ClassName();
}
Template parameters are for types, virtual inheritance needs pointers.
DerivedClass derived;
std::cout << StatusPrint(&derived) << std::endl; // note the &
cT is a type, not an object. You can only call functions on object instances (unless they're static functions, but that's not what you're trying to do here). You need to pass in an instance of the object you want to print out. e.g.
template<class T>
std::string StatusPrint(const T& obj, const std::string& message)
{
return obj.ClassName();
}
It's also customary to name template types with Uppercase to avoid this confusion.
I have to admit the compiler error for this is confusing, but it does give you a hint that there's something wrong with cT. It's saying that what comes before . is not what it was expecting.
With GCC 9:
error: expected primary-expression before '.' token
24 | return cT.ClassName();
| ^

typeid.name returns a number before the derived class type

I have these classes: (class Question is abstract the others are derived)
class Question{
};
class QSingleChoice{
};
class QMultipleChoice{
};
etc.
I have a vector<Question*> that stores multiple question types. In the GUI I need to know what type of question I have to show, so I'm using string questionType = typeid(*question).name() but instead of "QSingleChoice", "QMultipleChoice" etc. it returns "13QSingleChoice", "5QText", "9QOrdering" etc. What are those numbers? And can I suppose that they will be always the same or it's possible that when I run the program on a different computer, the typeid returns somethin like "19QSingleChoice" or something completely different like "ASDQSingleChoice"?
The name returned by std::type_info::name is implementation-defined, which means it's fully up to each compiler to decide how it wants to represent names of types. In other words, this is not something you could rely on. It's useful for debugging, and can be used for some comparisons within the same run of the program, but I wouldn't consider it usable for much more than that: you'd have to inspect your compiler's documentation to figure out if it offers the guarentees you need.
It's generally much better to introduce such functionality yourself if you need it, perhaps in the form of a virtual const std::string& classId() const;.
It could be implemented like this:
class Question {
public:
virtual const std::string& getClassId() const = 0;
};
class QSingleChoice : public Question {
public:
const std::string& getClassId() const override
{
static const std::string name{"SingleChoice"};
return name;
}
};
class QMultipleChoice : public Question {
public:
const std::string& getClassId() const override
{
static const std::string name{"MultipleChoice"};
return name;
}
};
Alternatively, you can create and return an enumeration instead of a string name.
However, first make sure that you actually need it in the first place. Quite often, the need to inspect and identify a particular type hiding behind an abstract interface indicates bad design. If the GUI is an integral part of the program, perhaps Question could simply offer virtual functions such as virtual void display() const;. Alternatively, if the GUI is largely external to the questions, perhaps using the visitor pattern might be more appropriate.

Virtual templated member function

I know that one can not have a virtual templated member function but I want something working similar to it.
Consider the following pseudo-code:
struct abstract
{
template<typename T>
virtual T get() const = 0;
};
using abstract_pointer = std::shared_ptr<abstract>;
struct concrete_int : public abstract
{
template<>
int get() const { return 123; }
};
struct concrete_string : public abstract
{
template<>
std::string get() const { return "abc"; }
};
abstract_pointer factory()
{
// Some logic here to decide what concrete type to return
return ...;
}
void print_value(abstract_pointer p)
{
// Will print either 123 or "abc"
std::cout << "p = " << p->get() << '\n';
}
int main()
{
abstract_pointer p = factory();
print_value(p);
}
The main code will only use the abstract_pointer type, it should not really know anything about the concrete classes.
It could easily be solved with CRTP and type deduction, but then it's not really possible to pass the object around to other function like in the example above.
I could also be using Boost variant, or unions, but then it could quickly become unwieldy if more concrete classes are added. I could also use Boost any, but then I would have to use any_cast and it would not be so... well, nice and simple.
It might just be that my google-fu is bad today, or I'm just too tired, but I haven't really found any way around it. Is it possible to do something like this while still keeping it flexible enough to add more concrete classes, and also keeping the interface simple and nice?
A little explanation about the use case: This is to be a part of a small lexical analyzer for a simple compiler I'm making (just for fun though), and the abstract class in the example above is the "token" class, and the concrete classes are specific tokens like "integer token" or "string token" or "identifier token".
The reason I want to use abstract/concrete classes and inheritance is because I want to make the lexer flexible enough to be used by multiple languages, so it should be easy to, for example, add a "identifier token" child class for "keyword token", and maybe even one concrete class for each keyword.
But maybe AaronI is correct that I try to hard to make something complex. I'll let this question stand in case someone comes up with a good solution, or finds a good duplicate, meanwhile I'll think more about it and see if I can come up with something acceptable myself.
struct abstract
{
virtual string get() const = 0;
};
using abstract_pointer = std::shared_ptr<abstract>;
struct concrete_int : public abstract
{
string get() const override { return "123"; }
};
struct concrete_string : public abstract
{
string get() const override { return "abc"; }
};
abstract_pointer factory()
{
// Some logic here to decide what concrete type to return
return ...;
}
void print_value(abstract_pointer p)
{
// Will print either 123 or "abc"
std::cout << "p = " << p->get() << '\n';
}
int main()
{
abstract_pointer p = factory();
print_value(p);
}
Easy-peasy. :)
Disclaimer: code not reviewed by compiler.
If you are planning to introduce new keywords as tokens and at the same time use generic smart pointer to access all the tokens then, it somewhat becomes necessary that 'token::get()' returns something which is fundamental enough to be understood by the code which calls 'token::get()'. Consider 'token' here as an abstract class.
If you are printing (using 'cout') the token via 'get()' and if some concrete token returns an object then 'cout' won't understand what that object is or how to print the object.
In such case converting all the tokens to some common fundamental type (say, 'char*' or 'string' as suggested by "Cheers and hth. - Alf") seems good.
Also, if printing is one of the requirement then, following function can be added to the abstract class:
virtual void token::print(ostream &);
In this way every concrete object will print itself.

Object needs to let function access all its data

When using encapsulation and "tell, don't ask"-principle properly, there should be no reason for one to ask information from an object.
However, I've ran into a situation (let me know if this design itself is terrible) where I have an object with a member variable pointing to a function outside of the class.
At some point of my application, there's a need for my object to call the function and the function should then act based on my object's status.
Here's an example class:
typedef void(*fptr)(Foo*);
class Foo {
public:
Foo(string name, fptr function);
void activate()
{
m_function(this);
}
private:
string m_name;
fptr m_function;
};
That's the class, now the developer can use the class like so;
void print(Foo *sender)
{
cout << "Print works!" << endl;
}
int main(int argc, char **argv)
{
Foo foo("My foo", &print);
foo.activate();
// output: "Print works!"
}
This all works fine, but what if I want to print the name of the sender?
All the functions are defined outside of the class, by other developers, so there's no way to access private variables.
In C#, you can just use the partial keyword to add a method to an existing class.
This is not possible in C++ though.
I could just ignore encapsulation and create a setter and getter for name and all other properties that might be needed by the function in the future.
This is pretty terrible solution, I should basically create setter and getter for everything there is in my class, since the function can do anything to my object.
Besides what's the reason of encapsulation, if I'm just gonna ignore it when I want to?
An other solution would be a struct that holds the required properties inside it:
struct FooBar {
string name;
};
typedef void(*fptr)(FooBar);
void Foo::activate()
{
FooBar fb;
fb.name = m_name;
m_function(fb);
}
But this is not much different from not using encapsulation, and it doesn't seem like a too good solution either.
What would be the best approach for this problem?
I would make activate() an abstract method and all the class' properties protected.
Also, there's no need for the fptr:
class Foo {
public:
Foo(string name);
virtual void activate() = 0;
protected:
string m_name;
};
Now when someone wants to use your class, he just inherits his own from it:
class MyFoo : public Foo {
public:
MyFoo(string name);
virtual void activate()
{
cout << m_name << " says: Hello World!" << endl;
}
};
int main(int argc, char **argv)
{
MyFoo foo("My foo");
foo.activate();
// output: "My Foo says: Hello World!"
}
And if you need many different Foo's with different functionality, just inherit multiple classes instead of declaring multiple functions.
Edit: Instead of inheriting a new class for every different Foo instance, you could inherit one class for all of them with all the different methods.
Now all left for activate is to decide which method to call; use enum for this:
enum MyFooFunction {
printName,
printHello
};
class MyFoo : public Foo {
public:
MyFoo(string name, MyFooFunction function);
void printName() { cout << m_name << endl; }
void printHello() { cout << "Hello!" << endl; }
virtual void activate()
{
switch(m_function) {
case printName:
printName();
break;
case printHello:
printHello();
break;
}
}
protected:
MyFooFunction m_function;
};
Seen from the outside, private variables don't exist, so developers cannot possibly "want" to print them.
If they do want then either the class members (or better, queries in the class returning their contents) should be public, the function a member of the class, or in specific cases some friend mechanism may be used.
To summarize, don't set out to break encapsulation - instead, reconsider the abstraction behind your encapsulation and, if needed, create new queries for properties of your class which weren't foreseen as useful back when the class was designed - but now are.
You might want to change your function parameter type to const string & if the function should be able to see the string, but the rest of the outside world shall not see it. Also you might consider to use std::function<void(const string &)> instead of your function type. This has two fundamental advantages: You can pass closures (also called lambdas) to your constructor and you can read it more easily. The edited code would look like this:
class Foo {
public:
template <typename F>
Foo(string name, F && function)
: m_name (std::move(name))
, m_function(std::forward<F>(function))
{
}
void activate()
{
m_function(m_name);
}
private:
string m_name;
std::function<void(const string &)> m_function;
};
The client code would look like
int main(int argc, char **argv)
{
Foo foo("My foo", [](const string & s){ cout << s << endl; });
foo.activate();
// output: "My foo"
}
You see that the client does not need to define an extra function, but can simply do it 'inline'.
What you're asking is "How can I keep my members private, but still give callbacks some way of accessing them?"
When you look at it that way, your struct FooBar solution is actually pretty reasonable. The only problem is that it's a bit inefficient. You would be better off passing a const FooBar& instead of passing FooBar by value.
Your struct FooBar solution is even better than partial classes, because you can specify exactly which members the callback should have access to.
Edit: Reading your struct FooBar solution more closely, I see you're thinking of tediously copying the members individually before passing them to the callback. You can skip all that just by putting a FooBar object in your Foo class, like so:
struct FooBar {
string name;
};
typedef void(*fptr)(const FooBar&);
class Foo {
public:
Foo(string name, fptr function);
void activate()
{
m_function(data);
}
private:
FooBar data;
fptr m_function;
};
It's worth pointing out that, with this solution, the callbacks cannot access m_function, unless you decide to put it in FooBar. This is what I meant when I said that you can specify exactly which members the callback should have access to.
Let's face it, C++ access control was designed with some use cases in mind, and are generally usable, but never claimed to cover everything. If you can't solve the situation with just private and friend, and arbitrary functions must be allowed to access the internals, then best way is to make them public and move on.
Setters will not move you forward for sure, just add complexity for nothing. If data is effective public don't try to mask that fact pretending like it wasn't.
Look for the root cause -- why on earth outsides want your members and rearrange that.
I could just ignore encapsulation and create a setter and getter for name and all other properties that might be needed by the function in the future. This is pretty terrible solution, I should basically create setter and getter for everything there is in my class, since the function can do anything to my object.
True - this is basically making implementation details public (and in most cases, not something you should do).
An other solution would be a struct that holds the required properties inside it:
[...] But this is not much different from not using encapsulation, and it doesn't seem like a too good solution either. What would be the best approach for this problem?
Actually it is very different. Consider that you are actually calling an external function with normal parameters:
struct EventData { string name, yadayada; }
class Foo
{
public:
void activate()
{
m_function( EventData(m_name, yadayada) );
}
};
This is not accessing private data (Foo accesses it's own private data, m_function accesses it's own parameter values), but dependency injection.
There are no architecture compromises with this approach.

How do I define an any-to-any mapping in c++?

I would like to define a completely generic mapping in c++ where I can map anything to anything.
I tried std::map but what should K and V be to make it general enough so I can map primitives or objects (as keys) to other primitives or objects (as values).
Or is there another mechanism I could use?
EDIT: For clarification, I am trying to define a relationship in the base class (from which all my classes are derived) that will allow me to attach arbitrary data to my classes. The simplest approach would be a be a name-value pair, where the above key is a string. I was wondering if i do something more generic?
Impossible- as it should be. Such a mapping would be worthless, since you can't depend on any meaningful behaviour of either key or value, and it's impossible to design either a binary relation or hash function that would be meaningful across "anything", or that could operate on any type, so it's nowhere near even the realm of possible.
Edit: There is nothing preventing std::unordered_map<std::string, boost::any>- or indeed, boost::any which happens to hold a std::unordered_map of some types.
However, your design appears highly questionable. You're basically completely subverting the compiler for no apparent benefit. Why would you derive every class from a common base? And why on earth would you want to attach arbitrary data? The usual way to put data in a class is to put it in the class, not blow all your safety and performance and sanity by trying to coerce C++ into being an interpreted language.
It is possible - so in this point I disagree with #DeadMG.
It is worthless - in this point full agreement,
However I do not understand that concept of answering, I mean "don't do it" answers instead "it can be done in this way, but my advise is don't do it". I do not pretend to be "life teacher" - I am just answering,
For values - use something like boost::any.
For keys - it is more complicated - because std::map defines order in keys. So generic keys must follow thess rules:
If real keys types are the same - use order from the real keys
If real keys are not the same - you must define order between types (like order of typeinfo::name())
Generic keys must be copy constructible
Let see my proposal for keys (using type erasure):
template <typename T>
struct GenKeyTypeOrder;
class GenKeyImplInt {
public:
// true if before other Key in other
virtual bool before(const GenKeyImplInt&) const = 0;
// type value
virtual int typeOrder() const = 0;
virtual GenKeyImplInt* clone() const = 0;
virtual ~GenKeyImplInt() {}
};
template <typename RealKey>
class GenKeyImpl : public GenKeyImplInt {
public:
GenKeyImpl(RealKey realKey) : realKey(realKey) {}
// true if before other Key in other
virtual bool before(const GenKeyImplInt& r) const
{
const GenKeyImpl* rp = dynamic_cast<const GenKeyImpl*>(&r);
if (rp) return realKey < rp->realKey;
return typeOrder() < r.typeOrder();
}
// type value
virtual int typeOrder() const { return GenKeyTypeOrder<RealKey>::VALUE; }
virtual GenKeyImpl* clone() const { return new GenKeyImpl(*this); }
private:
RealKey realKey;
};
class GenKey {
public:
// true if before other Key in other
friend bool operator < (const GenKey& l, const GenKey& r)
{
return l.impl->before(*r.impl);
}
template <typename T>
GenKey(T t) : impl(new GenKeyImpl<T>(t)) {}
GenKey(const GenKey& oth) : impl(oth.impl->clone()) {}
~GenKey() { delete impl; }
private:
GenKey& operator = (const GenKey& oth); // not defined
GenKeyImplInt* impl;
};
// define for every type you want be used as generic key
template <>
struct GenKeyTypeOrder<int> { enum { VALUE = 0 }; };
template <>
struct GenKeyTypeOrder<std::string> { enum { VALUE = 1 }; };
Full example at ideone
See also this article
You will need to make K and V be special objects.
The object will need to include what object type it is.
struct {
void *pointer;
string type;
// int type; // this is also possible
} Object;
The above Object can point to anything. However, it also needs something to say what type it is, hence the type string.
Then you need to be able to cast the pointer back to the required type, by reading what is in type.
Eg.
if (type == "int") cout << (int*)(myobject.pointer) << endl;
Anyways, if you do something like this, you are almost starting to build a loosely-typed interpreter, because for any operation you want to do with the object, you will need to check its type (whether you are adding, concatenating or printing the value to stdout).
It is probably better if you use a class object, and use inheritance to store any data you need.
class Object {
public virtual string to_string() {
return "";
}
};
Then if you want to store an integer:
class Integer : public Object {
int i;
public string to_string() {
char str[50];
sprintf(str,"%d",i);
return string(str);
}
public Integer operator=(int a) {
i=a;
return this;
}
};
This way you can define an interface of all the functions you want all objects to support.
Note that making the base Object class have virtual functions means that if you say:
Integer a;
a=5;
Object object = (Object)a;
cout << object.to_string << endl; // prints "5"
So that the function called is that defined by the actual (true) type of the object.