Class containing template dependent on the class member - c++

The goal is to make kind of "smart getter" that gets the value from the current object if it is present, if not, it looks for the value in the parent object.
So this ValueGetter class contains pointer to the object it is contained in (gets it as run time parameter in constructor) and pointer to member it operates on as template parameter.
This is the most simple example:
template <class StyleType, int StyleType::*value>
struct ValueGetter
{
ValueGetter(StyleType* containedIn);
int get();
// Looks if the value is present in this style,
// if not it looks for the value in the parent style
};
struct Style
{
Style *parent;
int a;
ValueGetter<Style, &Style::a> x; // Error: 'Style::a' : is not a type name, static, or enumerator
};
When I move the x outside of the scope of the class, it compiles.
Generally it is possible for class to contain template dependent on the class type, so why this doesn't work?
Is there any other way to solve this issue without storing the pointer to member in runtime in constructor? (So the structure would contain extra pointer for every value)
Edit: I just succesfully compiled it in GCC, but not in MSVC (2012), so is this MSVC compiler error?

I don't think pointers (not to confuse with pointer types as in T*) are allowed as template parameters in 03 C++, only type names, integral constants or enum constants. Not even float/double constants. That includes class member pointers.
Update:
Also, static non-type parameters work:
template <class StyleType, int *value>
struct ValueGetter
{
ValueGetter(StyleType* containedIn);
int get();
// Looks if the value is present in this style,
// if not it looks for the value in the parent style
};
struct Style
{
Style *parent;
static int a;
ValueGetter<Style, &Style::a> x; // Error: 'Style::a' : is not a type name, static, or enumerator
};

Related

Using Any class (similar to boost::any) in other templates

I have implemented a pure C++11 Any class (based on this code) which is similar to boost::any and works nicely if used directly.
However I need to use this now as template parameter to assign parameters to variables. Look at this:
class A {
IRecognizer<Any, Any> *_recognizer;
template <typename T1, typename T2>
A(IRecognizer<T1, T2> *x) : _recognizer(x) {
}
}
and
template<typename Symbol, typename ATNInterpreter>
class IRecognizer {
public:
virtual int getState() = 0;
};
Even though I could assign each template parameter to an Any variable, I'm not allowed to assign IRecognizer<T1, T2> to IRecognizer<Any, Any>. Is there a solution for this problem? The error message is:
Cannot initialize a member subobject of type 'IRecognizer<Any, Any> *'
with an lvalue of type 'IRecognizer<Token *, ParserATNSimulator *> *'
The reason I use the Any class is to have a common type that could be assigned with any class reference (similar to Java's Object, but C++ has no common object type from which all other classes derive).
Maybe a different approach is possible here? I'm open for suggestions.
You are trying to convert a IRecognizer<T1, T2> * to a IRecognizer<Any, Any> *. The only allowed pointer conversion is from a derived class pointer to a base class pointer (i.e. Derived* to Base*) or to a more cv-qualified pointer to the same type (i.e. Derived* to Derived const*) or both.
IRecognizer<T1,T2> is not in the same class hierarchy as IRecognizer<Any, Any>. They are two unrelated types. You can add a constructor to convert an IRecognizer<A,B> to an IRecognizer<C,D> if that makes sense, but you can't add a similar thing for pointers.
A pointer to X is not the same as an X.
While you can convert an X into a Y (a IRecognizer<T1,T2> into an IRecognizer<Any,Any>), you cannot convert a pointer to X into a pointer to Y.
You may not want a pointer here. Instead, you might want a value.
However, an interface is not a value.
Java generics are not like C++ templates. A Java generic Bob<Type> is a wrapper around Bob<Object> -- it is actually storing an Object, with a bunch of wrapping casts to-and-from in a layer on top of it.
You can write such wrappers in C++. As an example:
class IRecognizer_base {
public:
virtual int getState() = 0;
};
template<typename Symbol, typename ATNInterpreter>
class IRecognizer:public IRecognizer_base {
};
Now, suppose getState() returned a Symbol:
class IRecognizer_base {
public:
virtual Any getState_() = 0;
};
template<typename Symbol, typename ATNInterpreter>
class IRecognizer:public IRecognizer_base {
public:
inline Symbol getState() {
return getState_(); // whatever conversion required to go from `Any` to `Symbol`
}
};
here, we expose the fact that our objects actually return an Any, but in the interface we cast them over.
If you actually exposed what operations are actually different based on the template types, you can do type erasing tactics that let you store anything that can do those operations instead of a pointer to a specific type.

Hot to initialize static const member in specialized template code?

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. ...

c++ using struct enum as a parameter won't compile

If create an enum inside a struct for readability, mentioned here
How to avoid name conflicts for two enum values with the same name in C++?
I am planning to add more enums, here and in other situations, I just wanted to know why the struct wasn't compiling. Coming from C# and Java I was hoping for a simpler syntax –
And have the struct as the parameter to a constructor in a class, I cannot call it from the main.cpp of a console application.
It gives me the error **no matching function for call toBarEnc::BarEnc(BarEnc::Scheme::eScheme)’ ** main.cpp
Here is the Class
class BarEnc {
public:
struct Scheme
{
enum eScheme
{ ADJ1M2, ADJ3M6
};
};
BarEnc();
BarEnc(BarEnc::Scheme scheme);
}
in main.cpp
I call it
BarEnc barEnc = BarEnc(BarEnc::Scheme::ADJ3M6);
But if I change the parameter to an int in the constructor the code compiles
BarEnc(int scheme);
If I change it to the enum the code compiles
BarEnc(BarEnc::Scheme::eScheme scheme);
But when it is a struct, it does not compile. I am relative new to C++, using GCC 4.6 to compile on Linux, using 99 standard.
Is there a reason why I can't use a struct as a parameter?
Simple question: how your enum value should be converted to struct?
Simple answer: there is no way, since there is no suitable constructor.
Your struct has no members, it has only type (enum), so, I have no idea, what you want to do.
When you declare the constructor as
BarEnc(BarEnc::Scheme scheme);
you tell the compiler that the BarEnc constructor takes a structure as argument, and so you can't pass the enumeration value as it's an enumeration and not the structure.
In this case there is really no use for a separate structure just to define the enumeration, you can declare it directly in the surrounding class:
class BarEnc {
public:
enum eScheme {
ADJ1M2,
ADJ3M6
};
BarEnc(eShceme scheme);
};
Then when creating BarEnc objects you pass the enumeration value:
BarEnc barenc(BarEnc::eScheme::ADJ1M2);
You can use a struct as parameter.
But your struct BarEnc::Scheme in fact has no member.
and the const value BarEnc::Scheme::ADJ3M6 's type is BarEnc::Scheme::eScheme, it cannot auto convert to a struct.

function pointers between classes

I am having difficulty getting my head around how to pass a class member function to a subclass (not derived).
My top level class is like this:
class CTop
{
public:
CTop();
int func1(void);
private:
CFnList* _funcList;
};
CTop::CTop():
_funcList(0)
{
_funcList = new CFnList();
_funcList->addFnPtrToList(0, &CTop::func1);
}
int CTop::func1(void)
{
// Does some stuff...
}
My function list class is like this:
class CFnList
{
public:
// Public functions
CFnList();
void addFnPtrToList(int index, int (*fn)(void));
private:
// Fn pointer list
typedef struct
{
int index;
int (*fn) (void);
}fn_list_t;
// function pointer list
QVector<fn_list_t> _fn_list;
};
So basically here I have an instance of class CTop and one of its members is a pointer to a class CFnList. CFnList pointer is instantiated in the constructor of CTop. Then I want to pass in a pointer to one of CTop's member functions to CFnList by calling the following line:
"_funcList->addFnPtrToList(0, &CTop::func1);"
I get issue (quite rightly) that addFnPtrToList does not take the parameters (int, (CTop::*)()). So the compiler knows this function is a certain member function and not just a generic (maybe static) function.
Is there a way to pass the a pointer to the member function into the sub-class? In my case I want the sub-class to be able to call this function. I am thinking I probably have to make static member functions or something, but the syntax is eluding me on how to do this.
All help / advise appreciated.
Fodder
CTop::func1 is a member function. &CTop::func1 is NOT a function pointer, it is a pointer to member (function). Those can not be mixed either in storing or calling. it is not compatible with int (*fn)(void), as the latter takes no arguments and the former requires an object that is passed as the hidden this.
For these reasons you can't have a simple but uniform facility. You either can go with simple function pointers, or pairs of PTM+object pointer, or use wrappers -- handmade or stock like boost::function fueled by boost::bind. If you have C++11 or TR1 you can use the std:: equivalents of the latter.
A declaration in the form:
int (*fn)(void)
cannot point to a member function. It can only point to a free function. Philispophically, this is because the calling conventions for member functions are different then that for free functions. Consider for example the need for a this pointer in the context of a member function call.
The syntax for declaring a pointer-to-member-function is like this:
int (CTop::*fn)(void)
There is an entire section in the C++ FAQ dedicated to member function pointers. Check it out.
You are passing the member function as if it were a regular function. That fails to include the 'this' reference to the class. In order to pass member functions, you have to be able to re-reference it from the original 'this'. Take a look at the following, instead.
typedef void (CTop::*OBJFNC)(args);
_funcList = new CFnList();
_funcList->addFnPtrToList(0, this, &CTop::func1);
void addFnPtrToList(int index, CTop* pobj, OBJFNC pfnc)
{ ... Store both ...
}
Now elsewhere you can execute it with the following.
(pobj->*pfnc)(args);
Here is the final solution, it uses a mixture of passing the instance of the object CTop and usage of template class for CFnList:
My top level class is like this (more or less the same except for the declaration of _funcList to includes the class type and to pass in the "this" to the constructor:
class CTop
{
public:
CTop();
int func1(void);
private:
CFnList<CTop>* _funcList;
};
CTop::CTop():
_funcList(0)
{
_funcList = new CFnList(this);
_funcList->addFnPtrToList(0, &CTop::func1);
}
int CTop::func1(void)
{
// Does some stuff...
}
My function list class is like this:
template<class T>
class CFnList
{
public:
// Public functions
CFnList(T *parent);
void addFnPtrToList(int index, int (T::*fn)(void));
private:
// Pointer to the parent (or owner is perhaps more correct)
T* _parent;
// Fn pointer list
typedef struct
{
int index;
int (T::*fn) (void);
}fn_list_t;
// function pointer list
QVector<fn_list_t> _fn_list;
};
// Constructor
template <class T>
CFnList<T>::CFnList(T *parent) :
_parent(parent),
_fn_list(0)
{
}
// addFnPtrToList:
template <class T>
void CFnList<T>::addFnPtrToList(int index, int (T::*fn)(void))
{
_fn_list.append((fn_list_t){index, fn});
}
So the major changes are:
1. Pass the CTop type in by using changing CFnList into a template.
2. Pass in the instance of the object CTop (so that the pointer to the function can be called) by passing "this" into the constructor and then template class stores it as a pointer to the given template type.... vio-la!...easy :o
Thanks to all who contributed :))

Linked list with different elements , possible?

Hya,
Lemme explain my point.
template<typename T>
class node{
T data;
template<typename X>
node<X>* right; // can point to any node<typename> i know its wrong
}
so that i can do something like:
node<int> a;
a.data = 23;
node<float> b;
b.data =43.6;
a.right= b;
std::cout<< a.data <<a.right->data;
Another example:
template <class Type>
struct vnode {
Type data;
vnode<Type> * vnodenext;
// vrow what_to_put_here // **i don't want to use void ptrs neither want to cast back manually**
}
And in main function if I define vnode struct of type string and another vnode of type int, then what pointer def should I replace with vrow in vnode struct definition so that it can point to vnode of type int or other type of vnode? e.g.
vnode<string> mystring;
vnode<int> myint;
myint.vrow = &mystring
It isn't really possible to do what you want because when using templates you have to know the types involved at compile time. In contrast, walking a previously constructed linked list requires you to discover the types in the list at runtime.
To illustrate, consider this:
struct node_base {
virtual ~node_base() {}
}
template<typename T>
struct node : public node_base {
T data;
node_base* right;
}
Now you can certainly have a list of node_base*, and those nodes can contain any type of data that you want. Constructing the list is not a problem, since at the point you add nodes the static type of data is known and you can create a node<TData>.
Now the problem is how to get the data back. Assume that there's a function that returns the data inside a node, given a pointer to that node. What should be the functions return type? Clearly (unless you know from beforehand that all data types share a common base) there is no single type that can be returned. That leaves you with:
Returning a void*
Writing a templated function that receives the data type as an argument
However, #2 is not feasible in practice (although it works in theory). You cannot write the data type as a template argument because that would require you to know it at compile time, which defeats the purpose of a multi-data-type list.
Therefore, the only solution left is returning a pointer type (either a node_base* or a void* to the data itself) and then casting that pointer to a useful type using some mechanism.
In general, it's not possible in C++ without some kind of run-time support. But you can use variant type for the values of nodes, see http://www.boost.org/doc/libs/1_46_1/doc/html/variant.html for example.
You should derive your vnode template from a common ancestor, i.e.
struct vnode_base {
virtual ~vnode_base() {}
};
template <class Type>
struct vnode : vnode_base {
// ...
};
and use the vnode_base* type for the next-element pointers in your nodes. Since conversion rom base class to ancestors is implicit, the following assignment would be fine: a.right= &b;.
To check if a node has a particular type, use C++'s RTTI. There's not really a way to avoid this - you need some kind of runtime type checking.
vnode<float>* pf = dynamic_cast<vnode<float>* >(a.right);
if (pf) {
// here we go
}