Template Specialization:request for member which is of...

Hello,

I'm getting an error that says

1
2
3
4
|In member function 'void BASE<L*>::SET(L**) [with L = OBJECT]':|
75|instantiated from here|
43|error: request for member 'COPY_OBJECT' in '*((BASE<OBJECT*>*)this)->BASE<OBJECT*>::BASE_OBJECT', 
which is of non-class type 'OBJECT*'|


Briefly explaining it the code below tries to specialize a BASE object to accept objects of type OBJECT with either a single pointer or double pointer. The code compiles fine for an initialization

1
2
BASE<OBJECT> base_pointer;//this tries to use the first BASE class for single pointers
    base_pointer.SET(new OBJECT());


when the class definition for object looks like

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template <class L>
class BASE;
class OBJECT
{
    friend class BASE< OBJECT>;

    private:

        OBJECT* COPY_OBJECT;

    public:

    OBJECT(){}
    ~OBJECT(){}
};


but not if the code is setup like this below which gives the error I stated above?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <iostream>

template <class L>
class BASE;
class OBJECT
{
    friend class BASE< OBJECT*>;//this is meant to be used by the initialization BASE<OBJECT> base_single_pointer;

    private:

        OBJECT** COPY_OBJECT;

    public:

    OBJECT(){}
    ~OBJECT(){}
};

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <class L>
class BASE<L*> //the first class for double pointers; do I need <L*> here? I'm guessing on this.
{
    private:

        L** BASE_OBJECT;//this is initialized on startup

    public:

    BASE();
    ~BASE();
    void SET(L** data);
};

template <class L>
BASE<L*>::BASE(){ this->BASE_OBJECT = new L*();}
template <class L>
BASE<L*>::~BASE(){ delete (this->BASE_OBJECT);}

template <class L>
void BASE<L*>::SET(L** NODE)
{
      (this->BASE_OBJECT) = NODE;//this loads the object initialized BASE<OBJECT*> base_pointer;
      (this->BASE_OBJECT)->COPY_OBJECT = NODE;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <class L>
class BASE //the first class for single pointers
{
    private:

        L* BASE_OBJECT;//this is initialized on startup

    public:

    BASE();
    ~BASE();
    void SET(L* data);
};

template <class L>
BASE<L>::BASE(){ this->BASE_OBJECT = new L(); }
template <class L>
BASE<L>::~BASE(){ delete (this->BASE_OBJECT); }

template <class L>
void BASE<L>::SET(L* NODE)//this loads the object initialized BASE<OBJECT> base_pointer;
{
      (this->BASE_OBJECT) = NODE;
      (this->BASE_OBJECT)->COPY_OBJECT = NODE;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int main()
{
    BASE<OBJECT*> base_pointer;//this tries to use the first BASE class for single pointers
    base_pointer.SET(new OBJECT*());

    //BASE<OBJECT*> base_double_pointer;//this tries to use the first BASE class for double pointers
    //base_double_pointer.SET(new OBJECT*());

    return 0;
}


I see multiple issues with your code, but most importantly, I don't get what are you trying to do.

Second most importantly: your use of BASE<L> and BASE<L*> looks very illegal.

My explanation why the compiler doesn't stop with an error immediately follows. I MAY be completely wrong, please correct me if so!

1
2
template <class L>
class BASE<L*>


Means (correct me if wrong!!!): "There is a template object, called BASE, which is defined, probably in some other file. Now, use the not yet known template input L, combine it to make the BASE<L*> object, and use it as an input to the class creation operation."

What does the compiler do when it sees
1
2
template <class L>
class BASE<L*>
?

It says: do I know what BASE is? It is not a regular object because it has template argument. Therefore BASE is a template, which has not been defined yet (perhaps it will be in some other file). I am therefore asked to do something with an unknown template. Now in view of the context I should crash, but the specifications specifically request that when I see an unknown template, I defer evaluation until the object is explicitly used.


This version of your code compiles and links, but I have no clue if it does what you want it to.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <iostream>

template <class L>
class BASE;
class OBJECT
{
    friend class BASE< OBJECT*>;//this is meant to be used by the initialization BASE<OBJECT> base_single_pointer;

    private:


    public:
        OBJECT** COPY_OBJECT;

    OBJECT(){}
    ~OBJECT(){}
};

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <class L>
class BASE //the first class for double pointers; do I need <L*> here? No you don't!!!!
{
    private:

        L** BASE_OBJECT;//this is initialized on startup

    public:

    BASE();
    ~BASE();
    void SET(L** data);
};

template <class L>
BASE<L>::BASE(){ this->BASE_OBJECT = new L*();}
template <class L>
BASE<L>::~BASE(){ delete (this->BASE_OBJECT);}

template <class L>
void BASE<L>::SET(L** NODE)
{
      (this->BASE_OBJECT) = NODE;//this loads the object initialized BASE<OBJECT*> base_pointer;
      (*this->BASE_OBJECT)->COPY_OBJECT = NODE;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int main()
{
    BASE<OBJECT> base_pointer;//this tries to use the first BASE class for single pointers
    OBJECT* theObjectPointer=new OBJECT;
    OBJECT** theObjectPointerPointer=&theObjectPointer;
    base_pointer.SET( theObjectPointerPointer );

    //BASE<OBJECT*> base_double_pointer;//this tries to use the first BASE class for double pointers
    //base_double_pointer.SET(new OBJECT*());

    return 0;
}

Last edited on
> but most importantly, I don't get what are you trying to do.
I second that.


1
2
template <class L>
class BASE<L*>

> Means (correct me if wrong!!!): "There is a template object, called BASE, which is defined, probably in some other file
¿where is that code from?
The time that it is forward declared it only reads template <class L> class Base; (note that there is no <L*>)
When it uses class Base<L*> it is defined right there.

> I am therefore asked to do something with an unknown template. Now in view of the context I should crash,
It is not unknown, you have declared it
So at that point the compiler knows what Base is, a class.


> which is of non-class type 'OBJECT*'
That usually means that you forgot to dereference a pointer.

1
2
3
4
5
6
7
8
9
10
//void BASE<L*>::SET(L**) [with L = OBJECT]
//let's make the replacement

void BASE<OBJECT*>::SET(OBJECT** NODE)
{
      //OBJECT** BASE_OBJECT;
      (this->BASE_OBJECT) = NODE; //fine
      //(this->BASE_OBJECT)->COPY_OBJECT = NODE; //missing one dereference
      (*(this->BASE_OBJECT))->COPY_OBJECT = NODE; //fine
}

now look at the BASE<L> case
Thanks guys for the help, I guess the question isn't framed in reference to what this is really about so I guess I'll just tell you that I'm trying to create a linked list so that it can accept different datatypes. I know this is pointless since there's an std::list out there but I still want to understand these parts of the C++ language. Maybe I'm going about creating my linked list in the wrong way, I ended up with this code thinking this is how a pointer is templated like so

1
2
std::list<OBJECT*> LIST;
LIST.push_back(new OBJECT());


I added an extra initializer in int main for

BASE<OBJECT*> base_pointer_2;

But I'm getting some errors.

1
2
3
4
||In function 'int main()':|
|62|error: no matching function for call to 'BASE<OBJECT*>::SET(OBJECT*&)'|
|41|note: candidates are: void BASE<L>::SET(L**) [with L = OBJECT*]|
|47|note:                 void BASE<L>::SET(L*) [with L = OBJECT*]|



I added another function to it in order to accept single pointers

1
2
3
4
5
6
template <class L>
void BASE<L>::SET(L* NODE)
{
      (this->BASE_OBJECT) = NODE;//this loads the object initialized BASE<OBJECT*> base_pointer;
      (*this->BASE_OBJECT)->COPY_OBJECT = NODE;
}


Here's the code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <iostream>

template <class L>
class BASE;
class OBJECT
{
    friend class BASE< OBJECT*>;//this is meant to be used by the initialization BASE<OBJECT> base_single_pointer;

    private:


    public:
        OBJECT** COPY_OBJECT;

    OBJECT(){}
    ~OBJECT(){}
};

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <class L>
class BASE //the first class for double pointers; do I need <L*> here? No you don't!!!!
{
    private:

        L** BASE_OBJECT;//this is initialized on startup

    public:

    BASE();
    ~BASE();
    void SET(L** data);
    void SET(L* data);
};

template <class L>
BASE<L>::BASE(){ this->BASE_OBJECT = new L*();}
template <class L>
BASE<L>::~BASE(){ delete (this->BASE_OBJECT);}

template <class L>
void BASE<L>::SET(L** NODE)
{
      (this->BASE_OBJECT) = NODE;//this loads the object initialized BASE<OBJECT*> base_pointer;
      (*this->BASE_OBJECT)->COPY_OBJECT = NODE;
}
template <class L>
void BASE<L>::SET(L* NODE)
{
      (this->BASE_OBJECT) = NODE;//this loads the object initialized BASE<OBJECT*> base_pointer;
      (*this->BASE_OBJECT)->COPY_OBJECT = NODE;
}
int main()
{
    BASE<OBJECT> base_pointer_1;//this tries to use the first BASE class for single pointers
    OBJECT* theObjectPointer_1=new OBJECT;
    OBJECT** theObjectPointerPointer_1=&theObjectPointer_1;
    base_pointer_1.SET( theObjectPointerPointer_1);

    BASE<OBJECT*> base_pointer_2;//this tries to use the first BASE class for single pointers
    OBJECT* theObjectPointer_2=new OBJECT();
    base_pointer_2.SET( theObjectPointer_2 );

    return 0;
}


Topic archived. No new replies allowed.