C++ Question

Universal member-function definition, instanceable from both 'const' & 'non-const' objects

Is there a way to define a member function that is both accessible from 'const' & 'non-const' objects?

I need this for my

sList
implementation of list class. In it I want to declare a function which will take as a parameter another function with either 'const' or 'non-const' pointer to
sList
and will call it for each list in the current
sList
structure.

Here is its declaration:

template <typename T>
struct sList
{
sList(initializer_list<T>);

inline void DoForEachList(auto pFunc)
{
for(auto p = this; p; p = p->pNext)
pFunc(p);
}

~sList();

T dat;

sList *pNext = nullptr;
};


I'm using
auto pFunc
because I want to eventually pass lambdas too. So now if I have a const object of this type and call from it 'DoForEachList' passing as an argument lambda function with 1 arg from type 'auto'. My compiler will fail with something like:


error: passing
const sList<unsigned char>
as
this
argument of
void sList<T>::DoForEachList(auto:1)
[with
auto:1
=
main()::<lambda(sList<unsigned char>*)>
;
T
=
unsigned char
]' discards qualifiers [-fpermissive]


And the code calling
DoForEachList
:

void main()
{
extern const sList<unsigned char> cvobj;
cvobj.DoForEachList([] (auto pCurr) {/* Do something */});
}


Is there some way I can define the
DoForEachList
member function (or template of member function) like this:

template <typename T>
struct sList
{
inline void DoForEachList(auto pFunc) auto //either 'const' or none
{
for(auto p = this; p; p = pNext->pNext)
pFunc(p);
}

//...
};

Answer

You do need two separate functions if you want to overload on the constness of this. However, you can minimize duplication by offloading the work to a helper function.

You could use a friend function template for this, but I would normally prefer a static member function instead; you can then make it private or protected:

template <typename T>
struct sList
{
    void DoForEachList(auto pFunc)
    {
        DoForEachListHelper(*this, pFunc);
    }
    void DoForEachList(auto pFunc) const
    {
        DoForEachListHelper(*this, pFunc);
    }
private:
    static void DoForEachListHelper(auto&& self, auto pFunc)
    {
        for(auto p = &self; p; p = pNext->pNext)
            pFunc(p);
    }
};