Date: Fri, 19 Nov 2021 16:21:32 +0100
I agree with Nicolas that TAD on alias templates could work in
principle, there are just implementation difficulties. For example,
until very recently, clang would only consider the canonical form of
parameters and arguments, which would discard alias templates. Fixing
that would be a prerequisite for implementing this.
One problem that I see though is that this would make them pretty much
opaque when dependent template arguments are involved, which would
weaken our ability to perform template type checking (which allows us
to diagnose typing issues in templates even before they are
instantiated).
On Fri, Nov 19, 2021 at 4:16 PM Arthur O'Dwyer via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> On Fri, Nov 19, 2021 at 10:07 AM Nicolas Weidmann via Std-Proposals <std-proposals_at_[hidden]> wrote:
>>
>> Thank you for your replies.
>> But the problem you are raising with your example already exists now:
>>
>> template<typename> struct no_default_alias3;
>>
>>
>>
>> template<> struct no_default_alias3<int> {
>>
>> using type = std::vector<int>;
>>
>> };
>>
>>
>>
>> template<typename T> using alias3 = typename no_default_alias3<T>::type;
>>
>>
>>
>> template<typename T> void bar(alias3<T>) { }
>
>
> Here the signature of `bar` (looking through the "transparent" aliases) is
>
> template<typename T> void bar(no_default_alias3<T>::type) { }
>
> The template parameter `T` cannot be deduced, because it's "firewalled" behind a member typedef of a dependent type. This is the primary use-case for C++20 `std::identity` — as a type-deduction firewall:
>
> template<class T> void baz1(T a, T b);
> template<class T> void baz2(T a, typename std::identity<T>::type b);
> int main() {
> baz1(sizeof(int), 0); // deduction fails: `a` says T=size_t but `b` says T=int
> baz2(sizeof(int), 0); // deduction succeeds: `a` says T=size_t, and `b` does not contribute to deduction
> }
>
> We also define
> template<class T> identity_t = typename std::identity<T>::type;
> as an alias template so that we don't have to write out the whole long thing every time. This is "free" because the compiler will just look straight through aliases: `identity_t<T>` is exactly equivalent to `std::identity<T>::type` in every place it's written.
>
> HTH,
> Arthur
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
principle, there are just implementation difficulties. For example,
until very recently, clang would only consider the canonical form of
parameters and arguments, which would discard alias templates. Fixing
that would be a prerequisite for implementing this.
One problem that I see though is that this would make them pretty much
opaque when dependent template arguments are involved, which would
weaken our ability to perform template type checking (which allows us
to diagnose typing issues in templates even before they are
instantiated).
On Fri, Nov 19, 2021 at 4:16 PM Arthur O'Dwyer via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> On Fri, Nov 19, 2021 at 10:07 AM Nicolas Weidmann via Std-Proposals <std-proposals_at_[hidden]> wrote:
>>
>> Thank you for your replies.
>> But the problem you are raising with your example already exists now:
>>
>> template<typename> struct no_default_alias3;
>>
>>
>>
>> template<> struct no_default_alias3<int> {
>>
>> using type = std::vector<int>;
>>
>> };
>>
>>
>>
>> template<typename T> using alias3 = typename no_default_alias3<T>::type;
>>
>>
>>
>> template<typename T> void bar(alias3<T>) { }
>
>
> Here the signature of `bar` (looking through the "transparent" aliases) is
>
> template<typename T> void bar(no_default_alias3<T>::type) { }
>
> The template parameter `T` cannot be deduced, because it's "firewalled" behind a member typedef of a dependent type. This is the primary use-case for C++20 `std::identity` — as a type-deduction firewall:
>
> template<class T> void baz1(T a, T b);
> template<class T> void baz2(T a, typename std::identity<T>::type b);
> int main() {
> baz1(sizeof(int), 0); // deduction fails: `a` says T=size_t but `b` says T=int
> baz2(sizeof(int), 0); // deduction succeeds: `a` says T=size_t, and `b` does not contribute to deduction
> }
>
> We also define
> template<class T> identity_t = typename std::identity<T>::type;
> as an alias template so that we don't have to write out the whole long thing every time. This is "free" because the compiler will just look straight through aliases: `identity_t<T>` is exactly equivalent to `std::identity<T>::type` in every place it's written.
>
> HTH,
> Arthur
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Received on 2021-11-19 09:21:45