Date: Sun, 15 Dec 2019 17:41:49 -0600

On Fri, Dec 13, 2019 at 12:58 AM jianping z via Std-Proposals <

std-proposals_at_[hidden]> wrote:

> // example-1b.hpp : much more concise, no more duplicated code (less

> error prone)

> class elements

> {

> int elem[10];

> const? int& operator[](size_t n) const? { return elem[n]; }

> const? int* data() const? { return elem; }

> const? int* begin() const? { return elem; }

> const? int* end() const? { return elem+10; }

> }

>

I think this is pretty nice, and I appreciate the examples clearly

illustrating how this is intended to work.

const or not const isn't the only axis we have to deal with though - we

have one more: lvalue or rvalue. Today, optional::operator*() looks

something like this (reduced for sanity):

template <typename T>

class optional {

union { char _; T value; };

bool has_value;

public:

auto operator*() & -> T& { return value; }

auto operator*() const& -> T const& { return value; }

auto operator*() && -> T&& { return std::move(value); }

auto operator*() const&& -> T const&& { return std::move(value); }

};

Now, with the const? feature, I could reduce these four overloads to two:

template <typename T>

class optional {

union { char _; T value; };

bool has_value;

public:

auto operator*() const?& -> T const?& { return value; }

auto operator*() const?&& -> T const?&& { return std::move(value); }

};

It'd really be nice to just have the one overload here. But with &/&&, it

doesn't work as nicely since the question is no longer "to token or not to

token", but rather a choice of two tokens. Maybe that's... fine and we

could just say that &&? means & or && while const? means const or nothing.

So that this spits out four functions for us:

template <typename T>

class optional {

union { char _; T value; };

bool has_value;

public:

auto operator*() const?&&? -> T const?&&? { return static_cast<T

const?&&?>(value); }

};

Maybe this is too ugly, maybe we need a different way to pick references.

But regardless one problem is that we'd need these two to unpack

independently (that is, get the full cartesian product of {const, } x {&,

&&}). But this goes against one of your examples where you illustrated:

template<typename T>

const? T& max(const? T& a, const? T& b)

as become two function templates (rather than four).

This 4x thing comes up a lot. std::get for std::tuple for instance might

become:

template <size_t I, typename... Ts>

auto get(tuple<Ts...> const?&&?) -> tuple_element_t<I,

tuple<Ts...>>const?&&?;

Something to think about.

Barry

std-proposals_at_[hidden]> wrote:

> // example-1b.hpp : much more concise, no more duplicated code (less

> error prone)

> class elements

> {

> int elem[10];

> const? int& operator[](size_t n) const? { return elem[n]; }

> const? int* data() const? { return elem; }

> const? int* begin() const? { return elem; }

> const? int* end() const? { return elem+10; }

> }

>

I think this is pretty nice, and I appreciate the examples clearly

illustrating how this is intended to work.

const or not const isn't the only axis we have to deal with though - we

have one more: lvalue or rvalue. Today, optional::operator*() looks

something like this (reduced for sanity):

template <typename T>

class optional {

union { char _; T value; };

bool has_value;

public:

auto operator*() & -> T& { return value; }

auto operator*() const& -> T const& { return value; }

auto operator*() && -> T&& { return std::move(value); }

auto operator*() const&& -> T const&& { return std::move(value); }

};

Now, with the const? feature, I could reduce these four overloads to two:

template <typename T>

class optional {

union { char _; T value; };

bool has_value;

public:

auto operator*() const?& -> T const?& { return value; }

auto operator*() const?&& -> T const?&& { return std::move(value); }

};

It'd really be nice to just have the one overload here. But with &/&&, it

doesn't work as nicely since the question is no longer "to token or not to

token", but rather a choice of two tokens. Maybe that's... fine and we

could just say that &&? means & or && while const? means const or nothing.

So that this spits out four functions for us:

template <typename T>

class optional {

union { char _; T value; };

bool has_value;

public:

auto operator*() const?&&? -> T const?&&? { return static_cast<T

const?&&?>(value); }

};

Maybe this is too ugly, maybe we need a different way to pick references.

But regardless one problem is that we'd need these two to unpack

independently (that is, get the full cartesian product of {const, } x {&,

&&}). But this goes against one of your examples where you illustrated:

template<typename T>

const? T& max(const? T& a, const? T& b)

as become two function templates (rather than four).

This 4x thing comes up a lot. std::get for std::tuple for instance might

become:

template <size_t I, typename... Ts>

auto get(tuple<Ts...> const?&&?) -> tuple_element_t<I,

tuple<Ts...>>const?&&?;

Something to think about.

Barry

Received on 2019-12-15 17:44:25