Catskul Catskul - 1 month ago 7
C++ Question

Is it possible to parameterize the constness of a templated member function?

Templates make most things about a function signature parameterizable apart from the function name itself. But is it also possible to parameterize the constness of a member function?

Trivial, minimalist, non-templated example:

struct Foo {
Foo * self() { return this; }
Foo const * self() const { return this; }
};


vs straw-man templated hypothetical:

struct Foo {
template<typename T> T self() std::constness_of(T) { return this; }
};

Answer

But is it also possible to parameterize the constness of a member function?

No, you cannot. You don't have access in the function signature to the implicit object to which this points, so you can't dispatch on it or template on it in any way. cv-qualifiers on member functions have to be spelled out.

For more complicated member functions, you could have one invoke the other (typically the non-const invoking the const one to avoid UB) to avoid some code duplication.


Or you could always write a non-member friend:

struct Foo {
    template <class T,
        std::enable_if_t<std::is_base_of<Foo, std::decay_t<T>>::value>* = nullptr
        >
    friend T* self(T& x) { return &x; }
};

We need the SFINAE to ensure that self() isn't found for unexpected types like Wrapper<Foo>. Note that this is quite a big longer than your original code, so really only makes sense in the context of having complicated logic.

Would sure be amusing if UFCS was adopted and now we all write our const/non-const overloads via non-member friends that we still invoke as if they were members.

Comments