Typeid error

When I try to use typeid(), it gives me an error saying, “use of typeid requires -frtti”. Apparently I need to enable rtti somewhere in order to use this class. How do I do this, or am I misunderstanding.

Are you trying to use it as a special C++ language typeid feature or you have your own function named typeid?

If it is for your own function, please, choose another name so it does not conflict with C++ reserved name.

I’m trying to use it as a language typeid feature. I have included <typeinfo>.

They, probably, didn’t enable it in the V5 SDK and libraries.

@jpearman would know the answer.

I’d ask first what do you need the typeid() for. It might be nice for debugging, but for actual program logic, there are better ways to resolve polymorphism, depending on the use case.

1 Like

My method aims to determine what motor or motorgroup an unspecified parameter is equal to, and then return a particular enum based upon that motor/motorgroup. The problem with this is that I need to either start with comparing my parameter to a motor or comparing it to motor group, and if the type of the parameter doesn’t match the type of the object it’s being compared to, then the comparison causes an error(I am using the addresses of the motors/motor groups to compare them). My solution to this was to find out which class the parameter belonged to, and the first thing I came upon on the internet was typeid, but talking jpearman he’s told me this is disabled, and I don’t think I’m savvy enough to go into the files to enable it. Any ideas on a different way to safely compare a parameter when you don’t know its class, or to figure out that class would be appreciated.

My Code:

template<typename T>
motorState getStopper(T clump)
{
if(&clump == &wheels)
return wheelsStop;
if(&clump == &intake)
return intakeStop;
if(&clump == &catapult)
return catapultStop;
if(&clump == &armLift)
return armLiftStop;
}

P.S I have a very limited understanding of programming, and am kind of just cobbling things together lol.
P.S.S someone just suggested a try/catch, which probably isn’t good practice but will do for now.

I’m pretty sure you can use dynamic_cast to your advantage.
If the cast fails (returns nullptr), then you know that the object is not of that type.

Why are you using templates like this? Can’t you either overload a normal method, or use template specialization, or take a completely different approach (this is likely not the best solution for your need)?

If you want to keep using templates, you can also use

if(std::is_same<decltype(T), Motor>::value) {
 // T is a Motor
}
4 Likes

yes, it’s disabled. I’ll have a look and see if it would work, but I probably disabled it because much of the C++ standard library we use is permanently installed inside vexos and I think it was causing issues. We keep the standard library inside the V5 brain so executable code size is small and wireless downloads quick.

5 Likes

I’m still very new to c++ and used the first version of template that made sense. Anyway thanks for the suggestion, I’ll try it out!

THIS. My team even uses dynamic_cast to filter which autons are compatible with which robot type (think of a single codebase supporting multiple different robots and a generic auton selector code, where each auton routine could claim its compatibility with instantiated robot variant).

If all you need is to decide which instance of something a pointer (or a reference) points too, you can always upcast to void* and compare those bare addresses.

But from an architectural point of view, it looks to me that you’re trying to enhance the existing platform API. I would personally do that by wrapping the platform object in my own, enhanced classes. Those would delegate to the platform API and add whatever extra functions you need. You’d then instantiate your wrappers (which, in their constructors, would instantiate the corresponding platform class) and work with them directly.

While using templates, you could also use partial specialization - you pretty much tell the compiler that if it encounters one type, it should use one implementation, while with another type, it should use another. Like this:

#include <stdio.h>

class A {};
class B {};

A a1, a2, a3;
B b1, b2;

template <typename T>
int extraFeature(T &t);

template <>
int extraFeature<A>(A &a) {
    if (&a == &a1) return 1;
    if (&a == &a2) return 2;
    if (&a == &a3) return 3;
    return -1;
}

template <>
int extraFeature<B>(B &b) {
    if (&b == &b1) return 11;
    if (&b == &b2) return 12;
    return -1;
}

int main(int argc, char **argv) {
    printf("Using a2: %d\n", extraFeature(a2));
    printf("Using b1: %d\n", extraFeature(b1));
    return 0;
}

(Please note that the function signature uses object reference, your original code won’t work even if it compiled, since you were passing a copy of your original object - one allocated temporarily on your functions’s stack, thus never equivalent to one of your global instances.)

Also, since you mentioned a motor group - this is great case to compare VEX and PROS APIs - VEX motor_group is a wrapper for a collection of motors, while PROS (actually OKAPI-lib) MotorGroup extends a base class “AbstractMotor”, the same way a Motor extends AbstractMotor, where AbstractMotor actually defines all the relevant APIs. You could then limit yourself to AbstractMotor API and never really care whether your instance represent one motor or a bunch thereof.

3 Likes