Custom RTTI information using templates - c++

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.

"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>>();

Related

Why do we need to specify the type template parameter for each class function defintion?

Since we define the template type over the class declaration, why do we have to specify it after each function definition? I'm confused because its even in the same file so it seems almost unnecessary to have to specify it over every function and because we are using the :: operator shouldnt it go back to the class declaration and see that T is already defined.
I'm new to c++ and still need to clear up some misunderstandings.
#ifndef __Foo_H__
#define __Foo_H__
template <class T>
class Foobar{
private:
bool foo1(T);
bool foo2(T);
public:
FooBar();
};
template <class T> bool FooBar<T>::foo1(T data){
code..
}
template <class T> bool FooBar<T>::foo2(T data){
code..
}
#endif
First you may rename the argument as for normal function:
template <class U> bool FooBar<U>::foo1(U and_here_too){/**/}
It also manages to handle (partial) specialization:
template <> bool FooBar<int>::foo1(int i){/**/}
template <typename T> bool FooBar<std::vector<T>>::foo1(std::vector<T> v){/**/}
Templates are example of generic programming. The idea is to reuse code/algorithms. In languages with strict type control you come across seemingly unnecessary constraints. For instance you may have some sorting function doing great job in one project but incompatible with types used in another.
C++, C#, and Java introduce generic programming as templates (C++) and generics (C#, Java). In generics (let's talk about Java) classes are existing entities and class parameters serve mainly as type control service. That is their purpose in collections. When you inspect how list works you see list gathers Objects and cast back to the parameterized type only when the object is retrieved. When you write class you can only assume the parameterized type is Object or declared interface like in the following example:
class Test<T extends Comparable> {}
Here you can use T as Comparable. Unless you explicitly declare the interface, the parameter is treated as Object.
Now comes the difference between generics and templates. In C++ you can assume much more about the parameterized type in implementation. You can write sorting of objects of unknown type. In Java you have to at least know what is interface the parameter type. This causes that C++ have to build new class for each parameter (in order to check if the code is correct). Vector<int> **is completely separate type from **Vector<float>. While in Java there exists one class Vector<? extends Comparable>.
:: is scope operator. You can access scope of Vector<int> because the class exists, however, Vector does not.
As a result Java can compile generics and C++ cannot. All templates have to be available in headers to all programmers; you cannot hide it (there is some work to compile templates but I don't know what is its status).
So when you use generics you can refer to method Vector.add() while when templates you have to specify parameter template<class T> Vector<T>.
PS. since template parameter is integral part of class name you may use templates for compile time calculations like fibonaci sequence
template<int N> struct Fibonaci {
static const int element = Fibonacci<N-1>::data + Fibonacci<N-2::data>;
}
template<1> struct Fibonaci {
static const int element = 1;
}
template<0> struct Fibonaci {
static const int element = 0;
}

Static variable with templates

I want to store some additional information about classname during inheritance:
#define CLASS_TO_STRING(name) #name
class IBase {};
template <typename T>
struct BaseManager
{
static const char* MANAGER_TAG = CLASS_TO_STRING(T);
};
std::map<const char*, IBase*> mManagers;
template <typename T>
void addManager(BaseManager<T>* manager)
{
mManagers[T::MANAGER_TAG] = manager;
}
So, when I call addManager with some object of type inherited from BaseManager I get an error that BaseManager<TYPENAME>::MANAGER_TAG is undefined. I understand the reason of the problem but can't understand how to resolve it.
Apart from marcin_j's comment about in-class initialization (which works only in C++11 and for nonintegral types it requires constexpr), the real problem is this:
static const char* MANAGER_TAG = CLASS_TO_STRING(T);
When this line gets parsed by the preprocessor, CLASS_TO_STRING will turn T into the string literal "T". What's really going on here is that the preprocessor (the one performing macro substitution) has absolutely no idea of the template system and that T is a template parameter. You need a different approach here.
You can change const char* to constexpr but I am afraid all you will get from CLASS_TO_STRING(T) is T (at least g++ gives me T on output - and thats because preprocessor runs before compilation and template instantiation).
also instead of T::MANAGER_TAG, you should BaseManager<T>::MANAGER_TAG. And your BaseManager should inherit from IBase if :
mManagers[BaseManager<T>::MANAGER_TAG] = manager;
is supposed to work.
The reason you get your error is I suppose that in-class initialization of static data member, works only for const integral types.

template for handling user defined type and structure

I'm trying to define a template that can handle user defined types and structures. The issue so far is that I can not get information of the structure members through the type definition. The template is suppose to detect structure data type and handle different member types accordingly.
The solution I came up so far involves a vector of type strings that signal the member element count and type:
std::vector<std::string> typeList
The program then traverse the list and handle structure according to typeList. There is so far no checking against given structure at all so behavior is undefined if a different structure is passed in.
My question is that is there any elegant way that can achieve this? I'd prefer the solution to check the incoming structure itself to get such type list information instead relying on a second data structure.
Thanks ahead.
I think what your looking for is template specialization.
E.g we could write a serialize method which is implemented differently for specific types:
template<typename T>
void serialize(const T& val)
{
static_assert("No implementation for this type provided");
}
template<>
void serialize<std::string>(const std::string& val)
{
// std::string specific implementation here
}
Notice that partial specialization (specialization for mutli types) is only possible for class templates.
There is no way to inspect types genericaly (like in java or c#) but you can have your types providing informations on their own.
template<typename T>
class GenericSerializeable {};
struct Foo : public GenericSerializeable<Foo>
{
int bar;
static std::vector<std::string> GetMembers()
{
return {"bar"}; // we could of course return a more complex type here providing more informations
}
};
// lets assume for a moment here that partial specialization is possible for functions, this is just a proof of concept
template<typename T>
void serialize(const GenericSerializeable<T>& type)
{
for (auto name : T::GetMembers())
{
// do whatever you want with them here
}
}
The combination with template specialization and a "tag class" allows is to treat types aswell not providing this interface with the same function signature.

multiple functions with same name but different argument types as template parameter

I'm using xsd to create c++ code from a xml schema file. For a xml type multiple functions are created (for serialization etc).
If the type is called XmlType multiple functions of the following form are created:
XmlType XmlType_(const XmlType& a, const string& b)
string XmlType_(const XmlType& a)
...
This are normal functions and not members of XmlType and they all have the same name.
For XmlType2 the functions would be called XmlType2_.
I would like to write a utility template class for all the different xml types of my xml scheme. The different functions are going to be called insight this class. What I have so far is something like this:
template<typename T>
using TFunc1 = T (*)(const T&, const string&);
template<typename T>
using TFunc2 = string (*)(const T&);
template<typename T, TFunc1<T> func2, TFunc2<T> func2>
class XmlUtil {
...
};
When create an instance of the XmlUtil class if have to do it like this:
XmlUtil<XmlType, XmlType_, XmlType_> util;
This feels a bit redundant and gets worse, when I have to pass more functions as parameters.
I would like to use the util class like this:
XmlUtil<XmlType, XmlType_> util;
or even better like this
XmlUtil<XmlType> util;
The only way I can think of is to somehow use define, but it doesn't feel right.
Is there an other way to do this?
EDIT:
I'm using a define now:
#define TRPL(name) name, name ## _, name ## _
...
XmlUtil<TRPL(XmlType)> util;
I'll edit this, if I find something better (maybe override sets like Yakk suggested in his answer).
This:
XmlUtil<XmlType> util;
is impossible because there is no way to get from XmlType to XmlType_. Their relationship is discarded after the automatic code generator.
However this:
XmlUtil<XmlType_> util;
may be possible. You can deduce the function type of XmlType_ and then use the deduced return type which will be XmlType. I believe there are standard library function for this purpose.
As for the two different overloads, that may be trickier. I do not think that you can pass a function overload set as a template parameter, the resolution is done on the template argument in the context of the template parameter to one function. I don't think there is a way to defer this action without using the preprocessor.
So I would argue that you should use a #define. It is better than nothing.
This looks like a job for override sets.
static struct foo_override_set_type {
template<typename... Args>
auto operator()( Args...&& args ) const
->
decltype( foo( std::forward<Args>(args)... ) )
{ return ( foo( std::forward<Args>(args)... ) ); }
template<typename T>
operator T() { return foo; }
} foo_override_set;
Objects of type foo_override_set_type represent the entire override set of foo. Calling them with operator() does an override set lookup on foo and calls the resulting function. Casting them to a function pointer does the same thing as casting the token foo to a function pointer (or other value).
Your code generation can auto-generate such override set types. It can also make a traits class that maps from your type XmlType to the override set of XmlType_ functions via specialization.
Then, your XmlUtil<XmlType> can access the override set of XmlType_ via that traits class. It first instantiates the override set variable, then invokes () on it.
As an aside, #Xeo has a proposal to make creating such objects as easy as typing []XmlType_ in C++1y or C++1z.
Default template arguments in the class definition?
Like
template<typename T, TFunc1<T> func1 = XmlType_, TFunc2<T> func2 = XmlType_>
class XmlUtil {
// ...
};
You can use a trait class like this
template <typename T>
struct Trait{
typedef T type;
typedef T (*func1)(const T&, const string&);
typedef string (*func2)(const T&);
};
and make the class XmlUtil have one template parameter (let's name it Trait) and use Trait::type, Trait::func1 and Trait::func2. See here for full usage.
In the example, the type of XmlUtil goes like:
XmlUtil<Trait<XmlType> >
I've done it this way since I don't know well your problem. It might be the case that you can just define the Trait class right into XmlUtil and use
XmlUtil<XmlType>
Other variations are possible, it just depend on what you need.
You can read a very brief introduction to trait classes here. If you want to read more about this topic I suggest you Modern C++ (Alexandrescu).
I am not sure I fully understand what you are asking. The common approach for serialization and deserialization would be to create a factory (abstract factory) and resolve the construction of the objects dynamically. Note that this can be improved for complex structures, where the code generator can create member functions to extract the exact type of each one of the members.
But again, I don't fully understand what you are really trying to do... As a recommendation I believe it would help if you provided more of a description of the problem to solve, as the question focuses on how to make your solution work, and that implicitly discards other approaches that might be better designs.

"run time templates"

I'm pretty sure the answer is "you can't use templates, you have to use virtual functions (dynamic polymorphism)", but it seems like I'd have to duplicate a lot of code if I went that route. Here is the setup:
I currently have two classes, ColorImageSegmentation and GrayscaleImageSegmentation. They do essentially the same thing, but there are three differences
- they operate on different types (ColorImage and GrayscaleImage)
- a parameter, the dimensionality of the histogram (3 vs 1) is different
- The PixelDifference function is different based on the image type
If I create a class
template <TImageType>
class ImageSegmentation
{
};
I would be in good shape. However, I want to have this object as a member of another class:
class MyMainClass
{
ImageSegmentation MyImageSegmentation;
};
But the user needs to determine the type of MyImageSegmentation (if the user opens a grayscale image, I want to instantiate MyImageSegmentation<GrayScaleType>. Likewise for a color image, MyImageSegmentation<ColorType>.)
With derived classes, I could store a pointer and then do:
class MyMainClass
{
ImageSegmentation* MyImageSegmentation;
};
... user does something...
MyImageSegmentation = new ColorImageSegmentation;
but how would I do something like this with templates? The problem is I have a lot of:
typedef TImageType::HistogramType HistogramType;
typedef TImageType::PixelType PixelType;
sort of things going on, so I don't know how I would convert them to the dynamic polymorphic model without duplicating a whole bunch of code.
Sorry for the rambling... does anyone have any suggestions for me?
Thanks,
David
Maybe there are additional requirements you haven't told us about, but from what you have so far, you can pass the type down through the containing class:
template<typename TImage>
class MyMainClass
{
ImageSegmentation<TImage> MyImageSegmentation;
};
Most likely you'll need some layer of dynamic dispatch, but only at the highest level of abstraction:
struct IMainClass
{
virtual bool SaveToFile(std::string filename) = 0;
virtual bool ApplySharpenFilter(int level) = 0;
...
};
template<typename TImage>
class MyMainClass : public IMainClass
{
ImageSegmentation<TImage> MyImageSegmentation;
public:
virtual bool SaveToFile(std::string filename);
virtual bool ApplySharpenFilter(int level);
};
IMainClass* pMain = new MyMainClass<GrayscaleImage>();
You want to create a templated version of your objects but have those objects take different parameter types based on the templated parameter? That's not a very easy thing to integrate into a library but there are a few ways of going about it.
Take a look at unary_function for inspiration. There they are using templated traits to carry around the type parameters without having to work any sort of magic:
template <class Arg, class Result>
struct unary_function {
typedef Arg argument_type;
typedef Result result_type;
};
'unary_function' does not contain any functionality other than declaring typedefs. These typedefs, however, allow you to express in code and at compile time named equivalents between code segments. They leverage the way template parameters are checked.
What this means is that you can have objects that work on this:
template<typename T>
struct Foo{
typedef typename T::argument_type argument_type;
Foo(T _myFunc) : m_Func(_myFunc)
void myWrappedFunction(argument_type _argument){ m_Func( _argument ); }
};
which contains within it the value type of the arguments without having to specify them in advance. So if you have pixel_type or something similar for each of your image objects then simply stating typename T::pixel_type will call forward the type parameter you need.