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.
Related
I want to have classes with a static data member knowing the class's complete size. This is for storing singleton instances, in case you want to know the actual use case of this.
In my naive implementation of this feature, I wanted to use a mixin class to add the special data member to my class. The mixin class would have to know the complete class (in order to know the complete class's size), so I implement it using the Curiously Recurring Template Pattern, a little bit like this:
template<class ObjectType>
class SingletonOf
{
static inline /* some type same size as ObjectType */ instance_memory;
public:
void *operator new(std::size_t)
{
return &instance_memory;
}
void operator delete(void *)
{
}
};
class foo : public SingletonOf<foo> // CRTP used here, to let SingletonOf know foo
{
// foo data members...
// foo member functions...
};
void bar() {
foo *p = new foo; // calls SingletonOf<foo>::operator new and returns the instance memory
}
Cute, right? Well, I learned that the following in C++20 is ill-formed (note: in all the code samples below, the class foo and the function bar() do not change. Also I will not keep writing the empty definition of SingletonOf::operator delete, because you can remember that it's there):
template<class ObjectType>
class SingletonOf
{
static char inline instance_memory[sizeof(ObjectType)]; // syntax error: incomplete type
public:
void *operator new(std::size_t) { return instance_memory; }
...
Now, we will all agree the reason why that is ill-formed - and I am not complaining, just informing - is that ObjectType is foo, and until the closing brace of foo, foo is an incomplete type. And, obviously, sizeof cannot be called on incomplete types. So, I am fine with that. However, the following using a nested class-template does work - at least according to clang++ in c++20 mode, I think?
template<class ObjectType>
class SingletonOf
{
template<class CompleteObjectType>
struct InstanceMemory
{
static char inline instance_memory[sizeof(CompleteObjectType)];
};
public:
void *operator new(std::size_t) {
return InstanceMemory<ObjectType>::instance_memory;
}
...
Now my question is: why does that work? Or, let's start with the more fundamental question: does that work, actually? As of this writing, just to be clear, I have not verified that bar() actually calls the intended operator new and returns the foo-sized instance memory. Probably, should do that. But I'm busy. What I do know at this time, is that my clang++ in c++20 mode compiles it. This compilation includes compiling the function bar(), which allows me to be certain it instantiates the template. So that is to back up my contention that the compiler is accepting it. There are no errors or warnings give, just an output object file.
If I am right that this second code is well-formed, then it looks like ObjectType (= foo) in the body of operator new in the second code sample, is considered a complete type. How did that happen?
This isn’t really any different from having InstanceMemory defined in a namespace: until it is instantiated, its template argument need not be complete. This separation works because it removes the presumption that you should be able to use decltype(SingletonOf::instance_memory) immediately after declaring it.
When SingletonOf<ObjectType> is being instantiated, ObjectType is incomplete. That's why you can't get the size of it.
However, the member function bodies of SingletonOf work as if they are placed just after the type. And those functions get instantiated at a point when ObjectType is complete. This is why ObjectType is complete and visible to member functions of SingletonOf<ObjectType>.
Your inner struct InstanceMemory is itself a template. And you instantiate it within a member function of the outer template. Since that member function sees ObjectType as complete, so too does InstanceMemory<ObjectType>.
All you have to do is make sure to instantiate InstanceMemory<ObjectType> at a point where ObjectType is complete.
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>>();
I'm currently not able to set up my class members like I want to. My templated class is only specialized for sensible integer types (unsigned and “small”). Each specialization needs a rather big look-up table that only depends on the type. So I thought it should definitely be static (and const) and created only once.
As C++ doesn't have static constructors I learned that you can create a class that does the heavy stuff on initialization and have that as a static member.
I reduced my code to these basics:
// Of this, I only want one instance per type,
// because the table can get big.
template<class T>
struct LookUp
{
static int const SIZE = 1 << (sizeof(T) << 3);
std::vector<T> table;
LookUp()
: table{ SIZE }
{
for (int i = 0; i < SIZE; ++i)
{
// Dummy code
table[i] = i;
}
}
};
// "Normal" template class with common code for all types.
template<class T>
class LbpHelper
{
typedef /*...*/ image;
};
// No functionality for the general case.
template<class T>
class Lbp
{
};
// But for this (among others) we have something.
template<>
class Lbp<uint8_t> : public LbpHelper<uint8_t>
{
typedef uint8_t value_type;
typedef Lbp::image image;
static LookUp<value_type> _lookup; // <-- This is the mean one.
public:
// Stuff...
};
Initializing static members seems to confuse a lot of users, especially when it comes to templates and specialization. I read quite some answers here but none of them solved my problem.
I tried having something like
// The type of the class is the same as the type of the member class.
template<> LookUp<uint8_t> Lbp<uint8_t>::_lookup{};
template<> LookUp<uint16_t> Lbp<uint16_t>::_lookup{};
in the header or the source file or both. I tried with or without a class T in the angle brackets (and using T to the right of course), leaving out the template<> alltogether, having the {}s only in the source — I don't know what else. Nothing worked.
Visual C++ either tells me that _lookup is not a member or that it is not an entity that can be specialized or this: error C2373: '_lookup' : redefinition; different type modifiers.
Can someone please tell me what to put where so that it compiles?
Just drop the template<> bit, and put the definition of the static data members in a .cpp file:
LookUp<uint8_t> Lbp<uint8_t>::_lookup{};
LookUp<uint16_t> Lbp<uint16_t>::_lookup{};
[Live example]
... and, since the type of _lookup is a class, you can leave out the {} as well; its default constructor will be called anyway. This might please VC++ if you're using a version which does not support uniform initialisation.
Why this is the proper way: template<> is used to introduce explicit specialisations. You're not introducing an explicit specialisation - you're defining a data member of an already defined explicit specialisation.
This is covered by C++11 14.7.3/5:
... Members of an explicitly specialized class template are
defined in the same manner as members of normal classes, and not using the template<> syntax. The same
is true when defining a member of an explicitly specialized member class. ...
Is it better to do:
const int MY_CONST = 20; // global constant in the program
class A {
// uses MY_CONST all over the class implementation and definition
}
or this?
const int MY_CONST = 20; // global constant in the program
template<int my_const>
class A {
//uses my_const only and never MY_CONST
};
//A<MY_CONST> used later in the program
Is one of these pattern better than the other? why?
thanks
Unless that global constant is used elsewhere outside of the class I would use neither of those approaches and make the constant a member of A:
class A {
public:
static const int MY_CONST = 20;
};
const int A::MY_CONST; // Possibly need definition also
And then use A::MY_CONST in your code.
The only time I would use a template is when you need to change the value depending on the instance for some reason.
template <int I>
class A
{
public:
static const int MY_CONST = I;
};
template <int I>
const int A<I>::MY_CONST; // Definition
Then create instances like so:
A<1> a1;
A<2> a2;
The second solution is sensible if it makes sense to instantiate e.g. A<MY_CONST + 1>, or A<0>, or any other value than MY_CONST. If, however, A is strictly designed to be used with the one value, then you don't gain anything from that. In that respect the first solution gives you everything you need.
One way to look at it is that you're introducing a dependency to A (only on a number, not on anything with behavior, but still that's a kind of dependency), and the question is whether to inject that dependency via a template parameter, or have the class pull in the dependency via a named const object.
I can see the template being useful for testing the class A -- you want to write the class to work with any value, so that you can change the value in future with confidence that you won't immediately get test failures and have to fix the bugs.
So, you could write the template and test it with lots of different values, even though no "real" program will use more than one instantiation of the template.
Obviously there are other ways to write a class whose behavior depends on an integer value, and test it. For example you could use a macro and have the test harness compile the code multiple times, or you could make MY_CONST an extern value and link the code against different object files containing different values, or you could make A store the value as a data member (even a static data member).
Which ones work for you depends how the class is going to use the value, but since a template parameter is an integer constant expression it's good for most uses that the const int is good for. You can't take a template parameter's address, is the only thing that immediately springs to mind.
I would always remove the global variable. Let's distinguish 2 cases, MY_CONST is either
an implementation detail in which case I would prefer to make it a private constant
class A
{
private:
static int const MY_CONST = 20;
};
or part of the class interface in which case I would prefer to make it a template parameter and provide it as a public member
template<int N>
class A
{
public:
static int const MY_CONST = N;
};
This way, users can not only read but also "write" (at compile-time) to MY_CONST. If users will not want to specify anything but a default value for N, you could provide a default template argument, or give a simple typedef
typedef A<20> DefaultA;
I just found the following code in Qt and I'm a bit confused what's happening here.
Especially as to what reinterpret_cast<T>(0) does?
template <class T>
inline T qobject_cast(const QObject *object)
{
// this will cause a compilation error if T is not const
register T ptr = static_cast<T>(object);
Q_UNUSED(ptr);
#if !defined(QT_NO_MEMBER_TEMPLATES) && !defined(QT_NO_QOBJECT_CHECK)
reinterpret_cast<T>(0)->qt_check_for_QOBJECT_macro(*reinterpret_cast<T>(const_cast<QObject *>(object)));
#endif
return static_cast<T>(const_cast<QObject *>(reinterpret_cast<T>(0)->staticMetaObject.cast(const_cast<QObject *>(object))));
}
Anyone care to explain?
This is a little complicated...
Remember that qobject_cast<T>(obj) is a way to dynamically cast a QObject to the target type T which also derives from QObject. Now, for this to work, the macro Q_OBJECT should be included in the definition of class T.
Apparently, the qt_check_for_QOBJECT_macro call is for checking that the class really contains the Q_OBJECT macro. When the macro is expanded, it contains the following definitions:
template <typename T> inline void qt_check_for_QOBJECT_macro(const T &_q_argument) const
{ int i = qYouForgotTheQ_OBJECT_Macro(this, &_q_argument); i = i; }
template <typename T1, typename T2>
inline int qYouForgotTheQ_OBJECT_Macro(T, T) { return 0; }
So if you have an object x of type T and an object y of type U, the call x->qt_check_for_QOBJECT_macro(y) calls the function qYouForgotTheQ_OBJECT_Macro with parameters of types T* and U*. Because the function is templated with a single type parameter, the types T and U must be the same.
Now, if you call x->qt_check_for_QOBJECT_macro(x) then you should expect the types to be the same and for the compilation to trivially succeed. However, remember that this has the same type as the class the method was defined in. So if x is of a class that was derived from T but doesn't contain its own definition of qt_check_for_QOBJECT_macro, the call will fail.
So we have a way to check if the target type T contains the correct mechanism for the dynamic cast, but we don't have a object of type T to call this method on yet. That's what the reinterpret_cast<T>(0) is for. We don't need an actual object as this, since the compiler only needs the object types for the check to succeed. Instead, we call a method on a null pointer of type T.
I don't think this is allowed by the C++ standard, but it works since this isn't actually used inside the method.