Date: Sat, 12 Sep 2026 00:03:20 -0700
On Fri, Sep 11, 2026 at 11:43 PM Jefferson Carpenter <
jeffersoncarpenter2_at_[hidden]> wrote:
> Forwarded to list, corrected
>
> On Fri, Sep 11, 2026 at 4:47 PM Michael Park <mcypark_at_[hidden]> wrote:
> >
> > The semantics are slightly different, as these do not form an overload
> set. They are still matched
> > in order top-to-bottom, and require exact match.
>
> Why not? Do you have an example handy for why they shouldn't form an
> overload set?
>
In this example we happen to only have a set of declarations, but patterns
are richer in general.
Here's an example where it's not... obvious at all how overload resolution
would work over the cases:
#include <string>
#include <variant>
using Value = std::variant<int, std::string>;
void f(std::pair<int, Value> input) {
match (input) {
case [0, { int n }] => ;
case [0, { std::string s }] => ;
case [int tag, { int n }] => ;
case [int tag, { std::string s }] => ;
}
}
We have a pair of int and std::variant<int, std::string> being matched.
The pattern [0, { int n }] for example matches if .first == 0 and variant
has an int.
The rest of the patterns should be fairly intuitive I think.
There's not really much of an overload to be formed across those cases.
>
> > The braces denote that we're matching the element inside the variant.
> Without the braces,
> > it matches the whole variant rather than the stored element.
>
> Really a switch statement isn't the right thing to compare this with
> because a switch statement doesn't normally bind new variables.
>
> What I'd like to see is an expression-level construct for visiting
> variants. It needs to let me bind at least a single variable (the
> value inside the variant) (possibly letting me destructure it), and
> run statements of code yielding a value. (These statements mainly
> introduce new variables, but may utilize all variables in scope).
>
Ah, I only showed the match statement because you had mentioned wanting a
switch.
You can also use match as an expression. For example:
#include <variant>
struct MyClass { int num; };
int f(std::variant<MyClass, int> x) {
return match (x) {
case { MyClass myclass } => myclass.num;
case { int n } => n;
};
}
>
> > This distinction of payload vs whole extends to optional for example as
> well:
> >
> > match (opt) { // Assume opt is of type std::optional<int>
> > case {} => ; // nullopt
> > case { auto elem } => ; // elem is int
> > // vs
> > case auto whole => ; // whole is optional<int>
> > }
>
> What I'm proposing should be a distinct language feature from one for
> inspecting a
> value like the Pattern Matching proposal introduces. Can you propose
> an extension to
> the switch statement instead? You could write "switch (opt) { case
> {}: ...; case {let a}: ...;}"
>
The problem with switch is that the syntax for switch is not structured at
all.
The syntax for switch is essentially:
switch (value) *statement*
The *statement* there makes it such that any arbitrary sequence of
statements can
be written with cases written somewhere sometimes.
It also has too much baggage around fall-through and requiring break, etc.
The committee has been pretty firm on "leave switch alone".
On Fri, Sep 11, 2026 at 4:47 PM Michael Park <mcypark_at_[hidden]> wrote:
> >
> > Hello, P1371R3 was the previous iteration of pattern matching. The most
> recent version
> > discussed in EWG was P2688R5, which did not achieve consensus for C++26.
> >
> > I'm currently working on R6 of P2688, which I will be submitting for the
> upcoming Sept mailing.
> > I'm planning to present it in Buzios in November, and targeting C++29.
> >
> > As a small preview, with R6 the code you wrote:
> >
> > switch (x) { // Assume x is of type std::variant<MyClass, int>
> > case (MyClass myclass): { a(myclass); break; }
> > case (int n): { b(n); break; }
> > }
> >
> > would be written like this (CE link: https://godbolt.org/z/fMW1xdjz6):
> >
> > match (x) { // Assume x is of type std::variant<MyClass, int>
> > case { MyClass myclass } => a(myclass);
> > case { int n } => b(n);
> > }
> >
> > The semantics are slightly different, as these do not form an overload
> set. They are still matched
> > in order top-to-bottom, and require exact match. As such, for examples
> like this, it works out to be
> > the same (you can reorder the handlers in the match example, it's the
> same).
> >
> > The braces denote that we're matching the element inside the variant.
> Without the braces,
> > it matches the whole variant rather than the stored element.
> >
> > match (x) { // Assume x is of type std::variant<MyClass, int>
> > case { auto elem } => c(elem);
> > // vs
> > case auto whole => d(whole);
> > }
> >
> > This distinction of payload vs whole extends to optional for example as
> well:
> >
> > match (opt) { // Assume opt is of type std::optional<int>
> > case {} => ; // nullopt
> > case { auto elem } => ; // elem is int
> > // vs
> > case auto whole => ; // whole is optional<int>
> > }
> >
> > There's... A LOT more to share, but this is one of the important core
> ideas of R6.
> >
> > On Thu, Sep 10, 2026 at 3:49 PM Jefferson Carpenter via Std-Discussion <
> std-discussion_at_[hidden]> wrote:
> >>
> >> Actually the two are more or less the same. I think it would be much
> >> more readable to allow a statement-seq ending with a retrun statement
> >> to provide the value like a lambda expression than to try to construct
> >> matchers and extractors for whatever intermediate values you need.
> >>
> >> On Thu, Sep 10, 2026 at 5:07 PM Jefferson Carpenter
> >> <jeffersoncarpenter2_at_[hidden]> wrote:
> >> >
> >> > I definitely agree that matchers and extractors should not be language
> >> > features. Implementing these is like trying to invert a function.
> >> >
> >> > If the inspect expression is non-void, can a statement-seq be used
> >> > with a return statement to implement the value?
> >> >
> >> > - Jefferson
> >> >
> >> > On Thu, Sep 10, 2026 at 4:30 PM Jefferson Carpenter
> >> > <jeffersoncarpenter2_at_[hidden]> wrote:
> >> > >
> >> > > That looks good.
> >> > >
> >> > > On Thu, Sep 10, 2026 at 3:58 PM Jens Maurer <jens.maurer_at_[hidden]>
> wrote:
> >> > > >
> >> > > >
> >> > > > Please read the pattern matching proposal:
> >> > > >
> >> > > > P1371 Pattern Matching
> >> > > >
> https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1371r3.pdf
> >> > > >
> >> > > > Jens
> >> > > >
> >> > > >
> >> > > > On 9/10/26 21:05, Jefferson Carpenter via Std-Discussion wrote:
> >> > > > > Hi all,
> >> > > > >
> >> > > > > I'd like to propose some "syntactic sugar" that ties the switch
> >> > > > > statement language feature to the std::variant standard library
> type.
> >> > > > > The idea is to make the process of visiting a variant much
> cleaner and
> >> > > > > simpler.
> >> > > > >
> >> > > > > Basically it has to support the following code transformation:
> >> > > > >
> >> > > > > switch (x) { // Assume x is of type std::variant<MyClass, int>
> >> > > > > case (MyClass myclass): { a(myclass); break; }
> >> > > > > case (int n): { b(n); break; }
> >> > > > > }
> >> > > > >
> >> > > > > to the following:
> >> > > > >
> >> > > > > struct Unnamed {
> >> > > > > void operator()(MyClass const& myclass) { a(myclass); }
> >> > > > > void operator()(int const& n) { b(n); }
> >> > > > > };
> >> > > > > Unnamed{}(x);
> >> > > > >
> >> > > > > so that the code jumped to from each case is transformed into a
> >> > > > > function call operator overload. A braced-enclosed code block
> ending
> >> > > > > in a break statement may be required after each case "label"
> even when
> >> > > > > there are no variables declared in the body or if fallthrough
> were
> >> > > > > desired so that the code that must be moved is outlined and
> easy to
> >> > > > > move.
> >> > > > >
> >> > > > > This could potentially be extended to other non-std::variant
> types if
> >> > > > > there were a mechanism like std::get, but I haven't explored
> this at
> >> > > > > all.
> >> > > > >
> >> > > > >
> >> > > > > This would be very useful to me, as I've written a lot of
> >> > > > > programming-language-like programs and use std::variant
> extensively to
> >> > > > > represent expression trees.
> >> > > > >
> >> > > > > It would make C++ much more viable for programs like this to
> have the
> >> > > > > code for visitors easier to read and type than calls to
> std::visit.
> >> > > > >
> >> > > > >
> >> > > > > Warm Regards,
> >> > > > > Jefferson Carpenter
> >> > > >
> >> --
> >> Std-Discussion mailing list
> >> Std-Discussion_at_[hidden]
> >> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>
jeffersoncarpenter2_at_[hidden]> wrote:
> Forwarded to list, corrected
>
> On Fri, Sep 11, 2026 at 4:47 PM Michael Park <mcypark_at_[hidden]> wrote:
> >
> > The semantics are slightly different, as these do not form an overload
> set. They are still matched
> > in order top-to-bottom, and require exact match.
>
> Why not? Do you have an example handy for why they shouldn't form an
> overload set?
>
In this example we happen to only have a set of declarations, but patterns
are richer in general.
Here's an example where it's not... obvious at all how overload resolution
would work over the cases:
#include <string>
#include <variant>
using Value = std::variant<int, std::string>;
void f(std::pair<int, Value> input) {
match (input) {
case [0, { int n }] => ;
case [0, { std::string s }] => ;
case [int tag, { int n }] => ;
case [int tag, { std::string s }] => ;
}
}
We have a pair of int and std::variant<int, std::string> being matched.
The pattern [0, { int n }] for example matches if .first == 0 and variant
has an int.
The rest of the patterns should be fairly intuitive I think.
There's not really much of an overload to be formed across those cases.
>
> > The braces denote that we're matching the element inside the variant.
> Without the braces,
> > it matches the whole variant rather than the stored element.
>
> Really a switch statement isn't the right thing to compare this with
> because a switch statement doesn't normally bind new variables.
>
> What I'd like to see is an expression-level construct for visiting
> variants. It needs to let me bind at least a single variable (the
> value inside the variant) (possibly letting me destructure it), and
> run statements of code yielding a value. (These statements mainly
> introduce new variables, but may utilize all variables in scope).
>
Ah, I only showed the match statement because you had mentioned wanting a
switch.
You can also use match as an expression. For example:
#include <variant>
struct MyClass { int num; };
int f(std::variant<MyClass, int> x) {
return match (x) {
case { MyClass myclass } => myclass.num;
case { int n } => n;
};
}
>
> > This distinction of payload vs whole extends to optional for example as
> well:
> >
> > match (opt) { // Assume opt is of type std::optional<int>
> > case {} => ; // nullopt
> > case { auto elem } => ; // elem is int
> > // vs
> > case auto whole => ; // whole is optional<int>
> > }
>
> What I'm proposing should be a distinct language feature from one for
> inspecting a
> value like the Pattern Matching proposal introduces. Can you propose
> an extension to
> the switch statement instead? You could write "switch (opt) { case
> {}: ...; case {let a}: ...;}"
>
The problem with switch is that the syntax for switch is not structured at
all.
The syntax for switch is essentially:
switch (value) *statement*
The *statement* there makes it such that any arbitrary sequence of
statements can
be written with cases written somewhere sometimes.
It also has too much baggage around fall-through and requiring break, etc.
The committee has been pretty firm on "leave switch alone".
On Fri, Sep 11, 2026 at 4:47 PM Michael Park <mcypark_at_[hidden]> wrote:
> >
> > Hello, P1371R3 was the previous iteration of pattern matching. The most
> recent version
> > discussed in EWG was P2688R5, which did not achieve consensus for C++26.
> >
> > I'm currently working on R6 of P2688, which I will be submitting for the
> upcoming Sept mailing.
> > I'm planning to present it in Buzios in November, and targeting C++29.
> >
> > As a small preview, with R6 the code you wrote:
> >
> > switch (x) { // Assume x is of type std::variant<MyClass, int>
> > case (MyClass myclass): { a(myclass); break; }
> > case (int n): { b(n); break; }
> > }
> >
> > would be written like this (CE link: https://godbolt.org/z/fMW1xdjz6):
> >
> > match (x) { // Assume x is of type std::variant<MyClass, int>
> > case { MyClass myclass } => a(myclass);
> > case { int n } => b(n);
> > }
> >
> > The semantics are slightly different, as these do not form an overload
> set. They are still matched
> > in order top-to-bottom, and require exact match. As such, for examples
> like this, it works out to be
> > the same (you can reorder the handlers in the match example, it's the
> same).
> >
> > The braces denote that we're matching the element inside the variant.
> Without the braces,
> > it matches the whole variant rather than the stored element.
> >
> > match (x) { // Assume x is of type std::variant<MyClass, int>
> > case { auto elem } => c(elem);
> > // vs
> > case auto whole => d(whole);
> > }
> >
> > This distinction of payload vs whole extends to optional for example as
> well:
> >
> > match (opt) { // Assume opt is of type std::optional<int>
> > case {} => ; // nullopt
> > case { auto elem } => ; // elem is int
> > // vs
> > case auto whole => ; // whole is optional<int>
> > }
> >
> > There's... A LOT more to share, but this is one of the important core
> ideas of R6.
> >
> > On Thu, Sep 10, 2026 at 3:49 PM Jefferson Carpenter via Std-Discussion <
> std-discussion_at_[hidden]> wrote:
> >>
> >> Actually the two are more or less the same. I think it would be much
> >> more readable to allow a statement-seq ending with a retrun statement
> >> to provide the value like a lambda expression than to try to construct
> >> matchers and extractors for whatever intermediate values you need.
> >>
> >> On Thu, Sep 10, 2026 at 5:07 PM Jefferson Carpenter
> >> <jeffersoncarpenter2_at_[hidden]> wrote:
> >> >
> >> > I definitely agree that matchers and extractors should not be language
> >> > features. Implementing these is like trying to invert a function.
> >> >
> >> > If the inspect expression is non-void, can a statement-seq be used
> >> > with a return statement to implement the value?
> >> >
> >> > - Jefferson
> >> >
> >> > On Thu, Sep 10, 2026 at 4:30 PM Jefferson Carpenter
> >> > <jeffersoncarpenter2_at_[hidden]> wrote:
> >> > >
> >> > > That looks good.
> >> > >
> >> > > On Thu, Sep 10, 2026 at 3:58 PM Jens Maurer <jens.maurer_at_[hidden]>
> wrote:
> >> > > >
> >> > > >
> >> > > > Please read the pattern matching proposal:
> >> > > >
> >> > > > P1371 Pattern Matching
> >> > > >
> https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1371r3.pdf
> >> > > >
> >> > > > Jens
> >> > > >
> >> > > >
> >> > > > On 9/10/26 21:05, Jefferson Carpenter via Std-Discussion wrote:
> >> > > > > Hi all,
> >> > > > >
> >> > > > > I'd like to propose some "syntactic sugar" that ties the switch
> >> > > > > statement language feature to the std::variant standard library
> type.
> >> > > > > The idea is to make the process of visiting a variant much
> cleaner and
> >> > > > > simpler.
> >> > > > >
> >> > > > > Basically it has to support the following code transformation:
> >> > > > >
> >> > > > > switch (x) { // Assume x is of type std::variant<MyClass, int>
> >> > > > > case (MyClass myclass): { a(myclass); break; }
> >> > > > > case (int n): { b(n); break; }
> >> > > > > }
> >> > > > >
> >> > > > > to the following:
> >> > > > >
> >> > > > > struct Unnamed {
> >> > > > > void operator()(MyClass const& myclass) { a(myclass); }
> >> > > > > void operator()(int const& n) { b(n); }
> >> > > > > };
> >> > > > > Unnamed{}(x);
> >> > > > >
> >> > > > > so that the code jumped to from each case is transformed into a
> >> > > > > function call operator overload. A braced-enclosed code block
> ending
> >> > > > > in a break statement may be required after each case "label"
> even when
> >> > > > > there are no variables declared in the body or if fallthrough
> were
> >> > > > > desired so that the code that must be moved is outlined and
> easy to
> >> > > > > move.
> >> > > > >
> >> > > > > This could potentially be extended to other non-std::variant
> types if
> >> > > > > there were a mechanism like std::get, but I haven't explored
> this at
> >> > > > > all.
> >> > > > >
> >> > > > >
> >> > > > > This would be very useful to me, as I've written a lot of
> >> > > > > programming-language-like programs and use std::variant
> extensively to
> >> > > > > represent expression trees.
> >> > > > >
> >> > > > > It would make C++ much more viable for programs like this to
> have the
> >> > > > > code for visitors easier to read and type than calls to
> std::visit.
> >> > > > >
> >> > > > >
> >> > > > > Warm Regards,
> >> > > > > Jefferson Carpenter
> >> > > >
> >> --
> >> Std-Discussion mailing list
> >> Std-Discussion_at_[hidden]
> >> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>
Received on 2026-09-12 07:04:02
