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.
Related
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();
| ^
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.
I'm trying to write a lightweight library for parsing C source code.
Here's the way I've considered writing a declaration parser:
Decl CParser::ParseDecl(std::istream& in);
Or something like:
void CParser::Parse(std::istream& in);
// and
virtual void CParser::OnDecl(const Decl& decl);
Where Decl is a base class that may be inherited by either a TypedefDecl, FunctionDecl, or VariableDecl.
Is it okay that client code will have to cast into a derived class to get more information about the declaration? Or is there a better way to do this?
Edit:
The function itself isn't very well defined yet, it may actually be a callback, like CParser::OnDecl(const Decl& decl); which may be overloaded by a derived class like CFomatter: public CParser or something. That's not entirely part of the question.
I'm really just curious if it's okay that a client of the library will have to cast the Decl object. There's a lot of different declaration types in the C language (even more in C++) and it seems like writing a callback or a parser for each one of them would be just as bad as having to derive the base class.
First, of all you have to avoid slicing, for example by returning a a pointer.
Decl* CParser::ParseDecl(std::istream& in);
Then, generally speaking, forcing a client to cast a return value is a symptom of a bad design. What if he casts to the wrong type ? How shall he know to which type he has to cast ? If the user makes the wrong cast, it's undefined behaviour (and extremely nasty bugs).
CParser cp;
...
Decl* token = cp.ParseDecl(ifs);
FunctionDecl *ftoken;
VariableDecl *vtoken;
if (????) { // <============ how does your user know ?
ftoken = static_cast<FunctionDecl>(token);
//... do something with ftoken specific to function declarations
}
else if (????) {
vtoken = static_cast<VariableDecl>(token);
//... do something specific for variable declarations
}
To make the things more robust, you should at least make the type polymorphic, by having one or more virtual functions. Then your client can use the safer dynamic casting and make the right decision (which returns nullptr in case of wrong casting):
...
if (ftoken = dynamic_cast<FunctionDecl>(token)) { // If wrong type fotken will be set to nullptr and you go to the else part
//... do something with ftoken specific to function declarations
}
else if (vtoken = dynamic_cast<VariableDecl>(token)) { // attention: it's = and not ==
//... do something specific for variable declarations
}
This would be an acceptable design. But if you have polymorphic types, you could rethink your design by making use of this polymorphism, instead of forcing user to take care of casting. One possible way could for example be to define class specific functions as polymorphic ones:
class Decl {
public:
virtual void display_details() { cout << "No detail for this token"; }
...
};
class VariableDecl : public Decl {
...
display_details() { cout<<"This is variable "<<name; }
};
class FunctionDecl : public Decl {
...
display_details() { cout<<"This is function "<<name<<" with "<<nparam<< " parameters"; }
};
The user could then just refer to the specific building blocs, without worying to much about the real type of the object:
Decl* token = cp.ParseDecl(ifs);
token->display_details();
Another popular design for more complex situations is the visitor design pattern. This is for example used by boost::variant : it could be worth looking at their examples, event if you don't intend to use this library.
I have some classes:
class Base
{
public:
virtual void Something() = 0;
}
class A : public Base
{
public:
virtual void Something() { /*...*/ }
void SpecialActionForA();
}
class B : public Base
{
public:
virtual void Something() { /*...*/ }
void SpecialActionForB();
}
and an array:
Base* MyMembers[2];
MyMembers[0] = new A;
MyMembers[1] = new B;
and I want to do:
A* pointer_to_a = Get(0);
B* pointer_to_b = Get(1);
Is there any good way to implement this Get() function?
My solution is:
template <typename T>
T* Get(int index)
{
return dynamic_cast<T*>(MyMembers[index]);
}
But first thing is that I have to write
A* pointer_to_a = Get<A>(0)
Which requires an additional <A>;
Second thing is that if somehow the new is screwed up like:
MyMembers[0] = new B;
Then the Get() is failed.
What I want is something like an automatic mechanism which can maps index 0 to A.
Extra details:
Actually I have 80 different classes derived from Base (They are my User Interfaces),
and my need is to get the real classes (the real UIs) to do things.
The functions I need to use are the above SpecialActionForA()...etc.
The Something() is also used, but is in the initialization stage of these UIs, or something managed by the UI manager system.
You cannot do unknown* Get(int) in principle as it will require two or more functions having the same name but differing only by return value. C++ explicitly prohibits this.
The closest function that you can get is this:
template <typename T> T* Get() {
static T* instance = new T;
return instance;
}
so you will be able to use it as:
A *a = Get<A>();
B *b = Get<B>();
Overloading of function works by looking up the argument list. It is not possible to understand what kind of the value you want by judging only the return type. Thus compiler forces you to give extra detail to instantiate the template. So your options are:
Base *Get(int N) {
return MyMembers[N];
}
or
A *GetA(int N) {
return MyMembers[N];
}
B *GetB(int N) {
return MyMembers[N];
}
or
template <typename T> void Get(int N, T *&item) {
item = (T*)MyMembers[N];
}
A* pointer_to_a;
B* pointer_to_b;
Get(0, pointer_to_a);
Get(1, pointer_to_b);
or your own
template <typename T>
T* Get(int index)
{
return dynamic_cast<T*>(MyMembers[index]);
}
Without knowing your usage scenario, it'll be a bit hard to provide a useful answer, but I actually do believe what you want is type matching. So what you do is that you pass your variables around as Base pointers until I you actually need to know the concrete underlying type, at this point you do a matching on the underlying type of your base pointer. This is works pretty much alike a switch statement mixed with lambdas, I'll try to provide an example.
...
Base* ptr = some_argument;
// Here we need the underlying type, so we'll do a match
Match(ptr)
{
Case(A* a)
{
// this is invoked if ptr happened to hold an A, now do something A specific.
}
Case(B* b)
{
// this is invoked if ptr happened to hold a B, now do something B specific
}
Otherwise()
{
// this is invoked whenever none of the above are
}
}
EndMatch;
...
This is an alternative to the usual solution, which is virtual pointers in the base class, and overriding. Note that type matching is commonly used in functional languages. For C++ there's a cleaver solution to achieving this, by Yuriy Solodkyy one of Bjarne Stroustrup's PhD students.
The short introductury paper can be found here;
https://parasol.tamu.edu/~yuriys/papers/OPM13EA.pdf
For a more information, check out hvis paper, which was presented to the ISO comitee; Open and Efficient Type Switch for C++ by Stroustup, Dos Reis and Solodkyy
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3449.pdf
For the source code behind these papers goto Yuriys homepage at;
https://parasol.tamu.edu/~yuriys/pm/
If the number of classes you've got is truly closed, then consider using closed algebraic data types, as with boost::variant.These are have a few advantages over the unrestricted open algebraic data types, in that the compiler can usually ensure exhaustive matching, and in that the closed nature allows for more optimized pattern matching implementations, though at the cost of flexibility.
Also do note that boost::variant works nicely on C++03!
Do however please consider if you really need pattern matching or polymorphic dispatching. Both approaches are advantages and downsides, the main advance of the pattern matching approach, is that you aren't required to change your classes, and that you avoid polluting your base class with ultra specific virtual methods, which may only be called in a single location.
From the wikipedia article about Lambda functions and expressions:
users will often wish to define predicate functions near the place
where they make the algorithm function call. The language has only one
mechanism for this: the ability to define a class inside of a
function. ... classes defined in functions do not permit them to be used in templates
Does this mean that use of nested structure inside function is silently deprecated after C++0x lambda are in place ?
Additionally, what is the meaning of last line in above paragraph ? I know that nested classes cannot be template; but that line doesn't mean that.
I'm not sure I understand your confusion, but I'll just state all the facts and let you sort it out. :)
In C++03, this was legal:
#include <iostream>
int main()
{
struct func
{
void operator()(int x) const
{
std::cout << x << std::endl;
}
};
func f; // okay
f(-1); // okay
for (std::size_t i = 0; i < 10; ++i)
f(i) ; // okay
}
But if we tried doing this, it wasn't:
template <typename Func>
void exec(Func f)
{
f(1337);
}
int main()
{
// ...
exec(func); // not okay, local classes not usable as template argument
}
That left us with an issue: we want to define predicates to use for this function, but we can't put it in the function. So we had to move it to whatever outer scope there was and use it there. Not only did that clutters that scope with stuff nobody else needed to know about, but it moved the predicate away from where it's used, making it tougher to read the code.
It could still be useful, for the occasional reused chunk of code within the function (for example, in the loop above; you could have the function predicate to some complex thing with its argument), but most of the time we wanted to use them in templates.
C++0x changes the rules to allow the above code to work. They additionally added lambdas: syntax for creating function objects as expressions, like so:
int main()
{
// same function as above, more succinct
auto func = [](int x){ std::cout << x << std::endl; };
// ...
}
This is exactly like above, but simpler. So do we still have any use for "real" local classes? Sure. Lambda's fall short of full functionality, after all:
#include <iostream>
template <typename Func>
void exec(Func func)
{
func(1337);
}
int main()
{
struct func
{
// note: not possible in C++0x lambdas
void operator()(const char* str) const
{
std::cout << str << std::endl;
}
void operator()(int val) const
{
std::cout << val << std::endl;
}
};
func f; // okay
f("a string, ints next"); // okay
for (std::size_t i = 0; i < 10; ++i)
f(i) ; // okay
exec(f); // okay
}
That said, with lambda's you probably won't see local classes any more than before, but for completely different reasons: one is nearly useless, the other is nearly superseded.
Is there any use case for class inside function after introduction of lambda ?
Definitely. Having a class inside a function is about:
localising it as a private implementation detail of the code intending to use it,
preventing other code using and becoming dependent on it,
being independent of the outer namespace.
Obviously there's a threshold where having a large class inside a function harms readability and obfuscates the flow of the function itself - for most developers and situations, that threshold is very low. With a large class, even though only one function is intended to use it, it may be cleaner to put both into a separate source file. But, it's all just tuning to taste.
You can think of this as the inverse of having private functions in a class: in that situation, the outer API is the class's public interface, with the function kept private. In this situation, the function is using a class as a private implementation detail, and the latter is also kept private. C++ is a multi-paradigm language, and appropriately gives such flexibility in modelling the hierarchy of program organisation and API exposure.
Examples:
a function deals with some external data (think file, network, shared memory...) and wishes to use a class to represent the binary data layout during I/O; it may decide to make that class local if it only has a few fields and is of no use to other functions
a function wants to group a few items and allocate an array of them in support of the internal calculations it does to derive its return value; it may create a simple struct to wrap them up.
a class is given a nasty bitwise enum, or perhaps wants to reinterpret a float or double for access to the mantisa/exponent/sign, and decides internally to model the value using a struct with suitable-width bitfields for convenience (note: implementation defined behaviours)
classes defined in functions do not permit them to be used in templates
I think you commented that someone else's answer had explained this, but anyway...
void f()
{
struct X { };
std::vector<X> xs; // NOPE, X is local
}
Defining structures inside functions was never a particularly good way to deal with the lack of predicates. It works if you have a virtual base, but it's still a pretty ugly way to deal with things. It might look a bit like this:
struct virtual_base {
virtual void operator()() = 0;
};
void foo() {
struct impl : public virtual_base {
void operator()() { /* ... */ }
};
register_callback(new impl);
}
You can still continue to use these classes-inside-functions if you want of course - they're not deprecated or crippled; they were simply restricted from the very start. For example, this code is illegal in versions of C++ prior to C++0x:
void foo() {
struct x { /* ... */ };
std::vector<x> y; // illegal; x is a class defined in a function
boost::function<void()> z = x(); // illegal; x is used to instantiate a templated constructor of boost::function
}
This kind of usage was actually made legal in C++0x, so if anything the usefulness of inner classes has actually be expanded. It's still not really a nice way of doing things most of the time though.
Boost.Variant.
Lambdas don't work with variants, as variants need objects that have more than one operator() (or that have a templated operator()). C++0x allows local classes to be used in templates now, so boost::apply_variant can take them.
As Tony mentioned, a class inside a function is not only about predicates. Besides other use cases, it allows to create a factory function that creates objects confirming to an interface without exposing the implementing class. See this example:
#include <iostream>
/* I think i found this "trick" in [Alexandrescu, Modern C++ Design] */
class MyInterface {
public:
virtual void doSomethingUseful() = 0;
};
MyInterface* factory() {
class HiddenImplementation : public MyInterface {
void doSomethingUseful () {
std::cout << "Hello, World!" << std::endl;
}
};
return new HiddenImplementation();
}
int main () {
auto someInstance = factory();
someInstance->doSomethingUseful();
}