C++ Logo

std-proposals

Advanced search

Re: Apply CTAD features from C++17 to argument type of functions

From: Marcin Jaczewski <marcinjaczewski86_at_[hidden]>
Date: Wed, 27 May 2020 18:37:38 +0200
śr., 27 maj 2020 o 15:04 Stay Elite via Std-Proposals
<std-proposals_at_[hidden]> napisał(a):
>
> Compare class declaration with CTAD and function without CTAD:
>
> std::basic_string a("Hello, world!"); // deduce 'a' as std::basic_string<char, std::char_traits<char>, std::allocator<char> >
>
> template <class CharT, class Traits = std::char_traits<CharT>, class Allocator = std::allocator<CharT>>
> void foo(std::basic_string<CharT, Traits, Allocator> arg); // have to write all template argument to adapt all 'std::basic_string' type without CTAD
>
> Badly:
>
> foo(a); // OK: deduce 'CharT' as char
> foo("Hello!"); // Error, no match function for call to 'char[7]'
>
> So I have to provides another overload of foo:
>
> template <class CharT>
> void foo(const CharT *ptr)
> {
> foo<CharT>(ptr);
> }
>
> More badly, introduce 'std::basic_string_view', change argument type of the basic function to 'std::basic_string_view', and add a user-defined deduction guide:
>
> template <class CharT, class Traits = std::char_traits<CharT>, class Allocator = std::allocator<CharT>>
> std::basic_string_view(std::basic_string<CharT, Traits, Allocator>) -> std::basic_string_view<CharT, Traits>;
>
> template <class CharT, class Traits = std::char_traits<CharT>>
> void foo(std::basic_string_view<CharT, Traits, Allocator> arg);
>
> template <class CharT, class Traits = std::char_traits<CharT>, class Allocator = std::allocator<CharT>>
> void foo(std::basic_string<CharT, Traits, Allocator> arg)
> {
> foo(std::basic_string_view{arg});
> }
>
> template <class CharT>
> void foo(const CharT *ptr)
> {
> foo(std::basic_string_view{ptr}); // Can no longer use foo<CharT>
> }
>
> Let's apply CTAD to functions, all three template functions can be reduced to only one CTAD function with a user-defined deduction guide:
>
> template <class CharT, class Traits = std::char_traits<CharT>, class Allocator = std::allocator<CharT>>
> std::basic_string_view(basic_string<CharT, Traits, Allocator>) -> std::basic_string_view<CharT, Traits>;
>
> void foo(std::basic_string_view arg);


What is the point of new syntax for this? This is still a template
with now hidden parameters.
Compiler in any case need to compare `std::basic_string_view` with
`"world"` and resolve what exactly type we have.
Then when its known type we can deduce back what function template
parameters are.
Hiding them does not give us any advantage, and could in some cases
could reduce usefulness.

e.g.
```
template <class Traits, class Allocator>
void foo(std::basic_string<char, Traits, Allocator> arg);


foo("bar"); //Ok, deduction guide give defaults for `Traits` and `Allocator`
foo(u8"fiz"); //Error, different type `char` != `char8_t`

```



>
> Then just call like this:
>
> const char *ptr = "Hello, ";
> std::basic_string sz("world ");
> std::basic_string_view sv("CTAD");
>
> foo(ptr); // OK: deduce 'foo' as 'void foo( std::basic_string_view<char, std::char_traits<char>> ), pass 'ptr' as 'std::basic_string_view{ptr}'
> foo(sz); // OK: deduce 'foo' through the user-defined deduction guide, pass 'sz' as 'std::basic_string_view{sz}'
> foo(sv); // OK, of cource
>
> Q&A:
> 1. Is foo a template function?
> A: It's still a template function. CTAD doesn't change a class template to a normal class, neither did function.
>
> 2. How many function template is instantiated in this example?
> A: Only one. Depend on std::basic_string_view.
>
> 3. How could it be only one?
> A: All parameters of three calls construct the same type 'std::basic_string_view<char, std::char_traits<char>>' first. So there's just only one.
>
> 4. What if pass a type which cannot deduce to std::basic_string_view?
> A: Error, no match function for call to '<type>'.
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2020-05-27 11:41:06