Search code examples
c++c++20

Removing code duplication between const and non-const functions that return std::span?


If I have const and non-const versions of a function that returns a span:

class Foo {
public:
    std::span<int> myFunc() {
        auto begin{vec.begin()};
        auto end{vec.end()};
        
        // Do some work that modifies begin and end.
        
        return {begin, end};
    }

    std::span<const int> myFunc() const {
        // Same as above
    }

private:
    std::vector<int> vec{1, 2, 3};
};

Is there any way to avoid duplicating the function bodies?

I tried the const_cast approach, but got stuck on trying to cast the std::span return value.


Solution

  • const_cast method is fine as long as the returned value will not violate constness.

    Conversion from span<T> to span<const T> is possible but not the other way around.

    std::span<const int> Foo::myFunc() const
    {
        return const_cast<Foo*>(this)->myFunc();
    }
    

    Quoting from an answer to duplicate:

    NOTE: It is important that you do NOT put the logic in the non-const function and have the const-function call the non-const function -- it may result in undefined behavior. The reason is that a constant class instance gets cast as a non-constant instance. The non-const member function may accidentally modify the class, which the C++ standard states will result in undefined behavior.

    Therefore, you are advised to do the following.

    std::span<int> Foo::myFunc()
    {
        std::span<const int> const_span = static_cast<const Foo*>(this)->myFunc();
        return std::span<int>(const_cast<int*>(const_span.data()), const_span.size());;
    }