Question

Let's say I have the following template class:

template<typename T>
class A
{
public:
    // Lots of functions...

    void someFunc(T obj)
    {
        // T must implement this function in order to be usable within class A.
        obj.interfaceFunc();
    }
};

This works fine, as the object I will use with the template class implements interfaceFunc().

However, if I pass a pointer to the template class then the compilation fails because the dereference syntax is incorrect. Because the template class contains a lot of other functions that I don't want to copy/paste into another partial specialisation if I can possibly help it, I have changed my class definition as follows:

template<typename T>
class A
{
public:
    // Lots of functions...

    virtual void virtualHelperFunction(T* obj)
    {
        // We should never be here in the base class.
        assert(false);
    }

    void someFunc(T obj)
    {
        // Call the virtual function.
        virtualHelperFunction(&obj);
    }
};

// Partial specialisation 1
template<typename T>
class B : public A<T>
{
public:
    // ...

    virtual void virtualHelperFunction(T* obj)
    {
        obj->interfaceFunc();
    }
};

// Partial specialisation 2
template<typename T*>
class B : public A<T*>
{
public:
    // ...

    virtual void virtualHelperFunction(T* obj)
    {
        obj->interfaceFunc();
    }
};

However, when virtualHelperFunction() is called, on an instance of B but when inside the someFunc() function of the parent A, it hits the assertion error.:

B<SomeObject> instance;
instance.someFunc(SomeObject());  // Assertion failure.

I've tried messing around with function pointers to solve this but I'm still fairly new to them, and the non-static pointer syntax confused me a bit. I'm assuming one could define a member pointer to the virtualHelperFunction() which is set to point to the base class version in A's constructor, but which is then overwritten in B's constructor to point to B's function. If so, would anyone be able to demonstrate the correct syntax to do this?

Thanks.

EDIT: If context is needed, the template class is an octree node which stores a hash table of type T. The interface function required is that the object can return a bounding box, in order for recursive insertion to function depending on whether the object's bounds intersect with the tree node's bounds.

https://github.com/x6herbius/crowbar/blob/qt3d-experimental/Modules/Octree/inc/worldculltreenode.h https://github.com/x6herbius/crowbar/blob/qt3d-experimental/Modules/Octree/inc/worldculltreenode.tcc

Was it helpful?

Solution

This seems way too complicated. Why specialize the entire class if you just need one tiny bit specialized? All you need is a small utility that says "dereference this if it's a pointer, otherwise leave it alone". It could look like this:

template <typename T>
T& deref_if_pointer(T& t) { return t; }
template <typename T>
T& deref_if_pointer(T* t) { return *t; }

// ...
void someFunc(T obj) {
  deref_if_pointer(obj).interfaceFunc();
}

You can easily extend deref_if_pointer to various smart pointers as well; just add another overload.

OTHER TIPS

I'm not really sure what it is that you want to accomplish, so I'll have to guess. In what way does the following not satisfy your problem?

class A
{
public:
    // Lots of functions...

    void someFunc(T* obj)
    {
        // T must implement this function in order to be usable within class A.
        obj->interfaceFunc();
    }

    void someFunc(T obj)
    {
        // T must implement this function in order to be usable within class A.
        obj.interfaceFunc();
    }
};

If you want to do it that way, then you need to take a reference instead of a pointer in the first partial specialization:

template<typename T>
class A
{
public:
    // Lots of functions...

    virtual void virtualHelperFunction(T* obj)
    {
        // We should never be here in the base class.
        assert(false);
    }

    void someFunc(T obj)
    {
        // Call the virtual function.
        virtualHelperFunction(&obj);
    }
};

// Partial specialisation 1
template<typename T>
class B : public A<T>
{
public:
    // ...

    virtual void virtualHelperFunction(T& obj)
    {
        obj.interfaceFunc();
    }
};

// Partial specialisation 2
template<typename T*>
class B : public A<T*>
{
public:
    // ...

    virtual void virtualHelperFunction(T* obj)
    {
        obj->interfaceFunc();
    }
};

Your code doesn't compile. template<typename T*> is illegal and you do not have any partial specializations as you claim.

This works:

template<typename T>
class A
{
public:
    // Lots of functions...

    virtual void virtualHelperFunction(T* obj)
    {
        // We should never be here in the base class.
        assert(false);
    }

    void someFunc(T obj)
    {
        // Call the virtual function.
        virtualHelperFunction(&obj);
    }
};

// Unspecialized template
template<typename T>
class B : public A<T>
{
public:
    // ...

    virtual void virtualHelperFunction(T* obj)
    {
        obj->interfaceFunc();
    }
};

// Partial specialisation
template<typename T>
class B<T*> : public A<T*>
{
public:
    // ...

    virtual void virtualHelperFunction(T** obj)
    {
        (*obj)->interfaceFunc();
    }
};

int main() {
    B<SomeObject> instance1;
    instance1.someFunc(SomeObject());

    B<SomeObject*> instance2;
    SomeObject x;
    instance2.someFunc(&x);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top