C++ Logo

std-proposals

Advanced search

Re: Explicit alias template specialization

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Fri, 19 Nov 2021 11:55:59 -0500
On Fri, Nov 19, 2021 at 11:36 AM Marcin Jaczewski via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> pt., 19 lis 2021 o 17:28 Matheus Izvekov via Std-Proposals <
> std-proposals_at_[hidden]> napisał(a):
> >
> > On Fri, Nov 19, 2021 at 5:13 PM Arthur O'Dwyer via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
> > > Yes, they are.
> > > Dependent member types are (always?) non-transparent "firewalls"
> against deduction, but aliases are never(!) firewalls.
> >
> > If type aliases could be specialized as he proposed, then type aliases
> > specializations with dependent template arguments would indeed become
> > `firewalls` in all cases except that they could be matched one to the
> > other (as in the example from my previous message `alias<T>` would
> > match to `alias<int>` giving `T = int`).
> >
> > In the same way, it's possible to extend TAD such that dependent
> > member types could be matched.
> > So for example:
> > `P = typename T::foo` and `A = X:: foo` -> `T = X`
> > `P = typename foo<T>::bar` and `A = foo<int>::bar` -> `T = int`
>
> You can't go back from `bar` to `foo<T>` as `foo<T>::bar` is turing
> complete, you would need to check every possible `T` to find a one
> matching `bar`.
> Simple example:
> `P = typename T::foo` and `A = int` how to find `T` then?
>

To be fair, I assume that Matheus is talking only about the "true names" of
the types — like, the ones that contribute to mangling. (Do we have a
standardese term for "true names"? I've never been aware of one.)

So in that hypothetical (and definitely-never-gonna-happen) world where we
could deep-pattern-match into true names:

    template<class T> struct AA { struct Nested {}; };
    template<> struct AA<double> { using Nested = AA<char>::Nested; };
    template<> struct AA<float> { using Nested = float; };

    template<class T> void a(AA<T>::Nested);
    void a1() { a(AA<int>::Nested()); } // deduces T=int because the "true
name" of the argument type is AA<int>::Nested
    void a2() { a(AA<double>::Nested()); } // deduces T=char (not double!)
because the "true name" of the argument type is AA<char>::Nested
    void a3() { a(AA<float>::Nested()); } // deduction fails because the
"true name" of the argument type is float

And then we'd have:

    template<class T> void nonportable(std::vector<T>::iterator);
    void call_nonportable() { std::vector<int> v; nonportable(v.begin());
} // deduction fails today;
        // in the hypothetical world, deduction *probably* fails, but it
depends on your vendor's implementation details

If std::vector<int>::iterator is a typedef for __wrap_iter<int*>, then
deduction would still fail; if it's a class type with no intervening
aliases at all, then deduction would succeed.

–Arthur

Received on 2021-11-19 10:56:32