Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing a function of a templated interface with pointer as return type -> Conflicting return type error

I'm currently learning C++ and have come across the following problem: I have a templated interface BaseTemplate, which I would like to implement in a Child class without making the child a template itself. Sample code is as follows:

template <typename T>
class BaseTemplate
{
    public:
        virtual const T get() const = 0;
};

class Child : public BaseTemplate<int*>
{
    public:
        Child(int value) : myInt{value} {};
        virtual const int* get() const override { return &myInt; };

    private:
        int myInt{0};
};

int main()
{
    Child myChild = Child(10);
    std::cout << myChild.get() << "\n";
    return 0;
}

GCC produces the following error:

main.cpp|16|error: conflicting return type specified for ‘virtual const int* Child::get() const’
main.cpp|9|note: overridden function is ‘const T BaseTemplate<T>::get() const [with T = int*]’

I clearly understand that the error is related to virtual const int* get() const override { return &myInt; }; but I don't understand what's the problem. If I change the return type (of course in both classes) to int, i. e. return a value instead of a pointer, it works fine. So what's wrong with pointers here?

Maybe it helps: in my actual code, I want return a pointer to a custom interface instead of int, the error there is related I believe

file_trees.h|19|error: invalid covariant return type for ‘virtual const IDirectoryNode* FileTree::DepthFirstIterator::getCurrent() const’
iterator_interface.h|10|note: overridden function is ‘const T IIterator<T>::getCurrent() const [with T = IDirectoryNode*]’
like image 886
LosConikos Avatar asked Aug 22 '21 12:08

LosConikos


3 Answers

It has to due how const applies to types.

const T means the returned value is constant (that is of course almost useless). For pointers, this means the pointer itself is constant, not its target.

On the other hand, const int* is a non-constant pointer to a const int value.

For Base<int*>, T=int* yields int* const, not const* int, so you have to define int* const get() virtual method.

For T=const int* it would be const int* const. See this question for more details.

like image 180
Quimby Avatar answered Oct 28 '22 01:10

Quimby


When you have a

int *

The constant version of this type is not const int *. It is int * const, or a constant pointer to an int. const int * is a pointer to a constant int, which is a completely different type.

However, fixing the return type is insufficient, because get() is a const class method. Taking a pointer to it's data pointer produces a const int *, rather than an int *.

Probably the simplest fix here is to make this class member mutable:

class Child : public BaseTemplate<int*>
{
    public:
        Child(int value) : myInt{value} {};
        virtual int *const get() const override { return &myInt; };

    private:
        mutable int myInt{0};
};

Without fundamentally redesigning the entire class hierarchy, this is the minimal fix to get this to compile. You should fully understand what it means to make a class member mutable, and understand all implications.

like image 25
Sam Varshavchik Avatar answered Oct 27 '22 23:10

Sam Varshavchik


The const version of int* is int* const, which is a constant pointer to integer type, not pointer to const int.

What you intended could be achieved in the following way.

template<class T>
struct const_type_handler
{
    using type=const T;
};

template<class T>
struct const_type_handler<T*>
{
    using type=const T*;
};


template <typename T>
class BaseTemplate
{
    public:
        virtual typename const_type_handler<T>::type get() const = 0;
};

class Child : public BaseTemplate<int*>
{
    public:
        Child(int value) : myInt{value} {};
        virtual typename const_type_handler<int*>::type get() const override { return &myInt; };

    private:
        int myInt{0};
};

I know this makes the code kinda messy, but it works!.

like image 23
Karen Baghdasaryan Avatar answered Oct 28 '22 01:10

Karen Baghdasaryan