C++ Logo

std-proposals

Advanced search

More general version of const_iterator

From: Marcin Jaczewski <marcinjaczewski86_at_[hidden]>
Date: Mon, 2 Mar 2020 22:25:45 +0100
In my recent work I stumbled on problem that I need have two types
that have same members but different `const`-nes of them:

```
class C
{
    X* a;
    X* b;
    Y* c;
};

class C_const
{
    const X* a;
    const X* b;
    const Y* c;
};
```

My first thongs was that it should be some language mechanics that
will allow some thing like that e.g. new cv named `const_inner` that
will with some help for user convert type `C` to `C_const`. But after
some thoughts I see this is impossible (constructor and destructor are
not aware of cv, but they have need different implementation to make
it work). Aside from that we would double again number of function to
handle all possible cv combinations.
And this is probably simplest langrage change that could make it
happens, other could only make language more complicated.

But I see that std lib could reduce pain of defining this types and
handing them in generic way.
First we would need p0847r4, this on its own do not fix this problem
but as build block allow to fix this. Then we define new template
aliases:
```
template<typename T>
using const_inner_t = ??;
template<typename From, typename T>
using const_inner_as_t = ??;
```

Idea is this aliases will convert types like `T*`, `T&`,
`std::shared_ptr<T>` to:

```
static_assert(std::is_same_v<const_inner_t<T*>, const T*>);
static_assert(std::is_same_v<const_inner_t<T&>, const T&>);
static_assert(std::is_same_v<const_inner_t<std::shared_ptr<T>>,
std::shared_ptr< constT>>);
static_assert(std::is_same_v<const_inner_t<iterator>, const_iterator>);
//helper alias to switch between versions:
static_assert(std::is_same_v<const_inner_as_t<int, T*>, T*>);
static_assert(std::is_same_v<const_inner_as_t<const int, T*>, const T*>);
```

This with p0847r4 allow code like:
```
template<typename Dummy>
struct iterator_impl
{
    const_inner_as_t<Dummy, std::vector<int>::iterator> i;

    auto operator->() -> const_inner_as_t<Dummy, std::vector<int>::iterator>
    {
        return i;
    }
    //helper using that is used by `const_inner_t` to select correct
type for user defined types
    using const_inner = iterator_impl<const Dummy>;
};
using iterator = iterator_impl<void>;
using const_iterator = const_inner_t<iterator>;

template<typename Self>
auto foo(this Self f) -> const_inner_as_t<Self, iterator>
{
    return { f.vec.begin() };
}
```

if functionality like this would be common place it would heavy
simplify handling this problems that it would stop need language
solution to fix.

Received on 2020-03-02 15:28:37