0
votes

I have wrapper classes for SpiderMonkey API where I need to define methods with a specific signature. I have a solution based on templates. Basically, I have several template methods to handle hundreds of wrapper methods, like this (simplified):

template <typename jsType, AIErr(*Type::*Method)()>
    static bool ExecuteMethod(JSContext *cx, unsigned argc, JS::Value *vp)
{
...
}

I use it as follows, using macros:

#define EXECUTE_METHOD_AIERR_X(TYPE, METHOD) \
JS_FN(#METHOD, (js##TYPE::ExecuteMethod<js##TYPE, &TYPE::METHOD>), 0, 0)

If I have a situation when I need to debug, in order to know which method (*Method) of which class (*Type) was handled at a specific time, I would need to know the name of the type Type and the name of the method Method inside that template method. Due to the nature of SpiderMonkey's API, I can't alter the parameters of ExecuteMethod, just the template.

I've seen these:

C++ Get name of type in template

C++ Template Specialization with Constant Value

I've tried these, but the solution just fails for me at the typeid(T).name() step on MSVC C++ 2013 compiler. On the other hand, how to apply this on methods?

Additionally, I see this:

template<typename T>
class TypeParseTraits{
public:
    static const std::string name(){
        return typeid(T).name();
    }
};

#define REGISTER_PARSE_TYPE(X) \
    template<> class TypeParseTraits< X > \
    { public: static const std::string name(){ return #X; } };

What is this template<> class TypeParseTraits< X >? An override? A specialization?

If I would do it by templates again, it would be necessary to be dependent on jsType, Type and Method.

My question is, how should I implement (even for debug only) a RTTI info using strings? What are the most effective options, if any?

I know that simple char* is not an option as parameter for templates.

Thank you.

1
"What is this template<> class ...?" It's a template specialization.πάντα ῥεῖ
why and how does typeid fail?bolov
It's not clear what custom RTTI information should be. There's no such thing IIRC.πάντα ῥεῖ
"I would need to know the name of the type and the name of the method."mike
Assuming I have this: template <typename jsType, AIErr(*Type::*Method)()> static bool ExecuteMethod(JSContext *cx, unsigned argc, JS::Value *vp) { const char* jst = typeid(jsType).name(); const char* t = typeid(Type).name(); const char* m = typeid(Method).name(); const type_info& jsti = typeid(jsType); const type_info& ti = typeid(Type); const type_info& mi = typeid(Method);, the method name won't be retrieved, or I don't know how.mike

1 Answers

2
votes

"What is this template<> class TypeParseTraits< X >? An override? A specialization?" - it is partial specialization of template. In this particular case given macro ensures that TypeParseTraits template instantiated with 'registered' type will have method name that returns const std::string that contains the name of type, used in code instead of anything returnad by type_info.name() (which is implementation-defined and often hard to understand).

My question is, how should I implement (even for debug only) a RTTI info using strings? What are the most effective options, if any? - the best way for RTTI should be just some virtual method that will return for example a string. This method should be overriden in all derived classes (that could be simplified with static polymorphism approach) and return respective info.

I know that simple char is not an option as parameter for templates.* - not in general, but...

  • it is possible to have static const char* data in struct or class
  • is possible to fill this data with the help of template
  • it is possible to pass such struct as a template parameter and extract static data
  • it is possible to fill such strings manually if the member is constexpr (with some penalties though)

Thus you may use types (possibly templates) to pass char*s into other templates.

Example:

template<class C>
struct Named { static const char* name; };
template<class C>
const char* Named<C>::name = typeid(C).name(); // fill as you wish

template<class N>
void print() { cout<< N::name <<endl;}
...
print<Named<int>>();