Questions about P0091: Template argument deduction for class templates

119 views
Skip to first unread message

TONGARI J

unread,
Jul 10, 2016, 3:34:16 AM7/10/16
to ISO C++ Standard - Future Proposals
P0091 is voted into C++17, but for outsiders it's unclear what decisions/changes has been made since:

* What's the syntax settled for explicit deduction guides?

The proposed syntax in P0091R2 is:
    template < template-parameter-list > class-name ( parameter-declaration-clause ) -> simple-template-id

The author also listed some alternatives and left the decision to the committee, what's the committee's decision?
Is it possible for a syntax that doesn't require us to repeat the class-name twice, e.g:
    template-parameter-list > simple-template-id auto( parameter-declaration-clause )

template<typename Iter>
vector
<typename iterator_traits<Iter>::value_type> auto(Iter b, Iter e);

* Are non-template explicit deduction guides allowed?

template<class T>
struct S
{
    S
(T);
};

S
(char const*) -> S<std::string>;

S s
{"hello"}; // deduced to S<std::string>

* Does the deduction work for aggregates?

template<class A, class B>
struct Agg
{
    A a
;
    B b
;
};

Agg agg{1, 2.0}; // ok? deduced to Agg<int, double>

If the above doesn't work, will explicit deduction guides help?

template<class A, class B>
Agg(A a, B b) -> Agg<A, B>;


Richard Smith

unread,
Jul 11, 2016, 5:54:08 PM7/11/16
to std-pr...@isocpp.org
On Sun, Jul 10, 2016 at 12:34 AM, TONGARI J <tong...@gmail.com> wrote:
P0091 is voted into C++17, but for outsiders it's unclear what decisions/changes has been made since:

* What's the syntax settled for explicit deduction guides?

The proposed syntax in P0091R2 is:
    template < template-parameter-list > class-name ( parameter-declaration-clause ) -> simple-template-id

The author also listed some alternatives and left the decision to the committee, what's the committee's decision?

The proposed syntax was accepted.
 
Is it possible for a syntax that doesn't require us to repeat the class-name twice, e.g:
    template-parameter-list > simple-template-id auto( parameter-declaration-clause )

template<typename Iter>
vector
<typename iterator_traits<Iter>::value_type> auto(Iter b, Iter e);

There is no support for such a syntax.
 
* Are non-template explicit deduction guides allowed?

template<class T>
struct S
{
    S
(T);
};

S
(char const*) -> S<std::string>;

S s
{"hello"}; // deduced to S<std::string>

Yes, this is permitted.

* Does the deduction work for aggregates?

template<class A, class B>
struct Agg
{
    A a
;
    B b
;
};

Agg agg{1, 2.0}; // ok? deduced to Agg<int, double>

No, you can't do that; the deduction only considers constructors. This seems like a reasonable extension, though.
 
If the above doesn't work, will explicit deduction guides help?

template<class A, class B>
Agg(A a, B b) -> Agg<A, B>;

Yes, that should work.

Nicol Bolas

unread,
Jul 11, 2016, 6:36:08 PM7/11/16
to ISO C++ Standard - Future Proposals

Wait, what? Deduction doesn't work for aggregate templates, because they have no constructor. But you can add this deduction syntax to make it work.

Is this considered to give `Agg` a constructor? That is, is `Agg` no longer an aggregate?

Richard Smith

unread,
Jul 11, 2016, 7:58:24 PM7/11/16
to std-pr...@isocpp.org
No, class template argument deduction happens before initialization, and deduction guide declarations are not used for anything other than guiding class template argument deduction.

In the declaration

  Agg agg{1, 2.0};

we perform overload resolution as if we were initializing an object of some hypothetical type X and we had the following overload set of constructors for X:

  template<class A, class B> X(); // implicit, from class template
  template<class A, class B> X(const Agg<A, B> &); // implicit, from class template
  template<class A, class B> X(Agg<A, B> &&); // implicit, from class template
  template<class A, class B> X(A a, B b); // from deduction guide

We pick #4 (which doesn't matter) and deduce A=int, B=double. Those types are then substituted into the simple-template-id from the deduction guide, giving the type Agg<int, double> as the type of agg.

With that type deduced, we then initialize agg normally, which in this case happens to perform aggregate initialization.

Zhihao Yuan

unread,
Jul 11, 2016, 8:20:05 PM7/11/16
to std-pr...@isocpp.org
On Mon, Jul 11, 2016 at 6:58 PM, Richard Smith <ric...@metafoo.co.uk> wrote:
> With that type deduced, we then initialize agg normally, which in this case
> happens to perform aggregate initialization.

So this works as well?

template <template... T>
array(T&&... t) -> array<common_type_t<T...>, sizeof...(T)>;

auto a = array{ 1, 2, 3u };

For the example raised before, does this work?

Agg<long> agg{1, 2.0}; // deducing only B

(I guess not as the wording seems not having this grammar).

--
Zhihao Yuan, ID lichray
The best way to predict the future is to invent it.
___________________________________________________
4BSD -- http://blog.miator.net/

Richard Smith

unread,
Jul 11, 2016, 9:22:31 PM7/11/16
to std-pr...@isocpp.org
On Mon, Jul 11, 2016 at 5:20 PM, Zhihao Yuan <z...@miator.net> wrote:
On Mon, Jul 11, 2016 at 6:58 PM, Richard Smith <ric...@metafoo.co.uk> wrote:
> With that type deduced, we then initialize agg normally, which in this case
> happens to perform aggregate initialization.

So this works as well?

  template <template... T>
  array(T&&... t) -> array<common_type_t<T...>, sizeof...(T)>;

  auto a = array{ 1, 2, 3u };

Yes, that should work.

For the example raised before, does this work?

  Agg<long> agg{1, 2.0};  // deducing only B

(I guess not as the wording seems not having this grammar).

No, if an explicit template argument list is written, class template argument deduction is not performed. Various concerns were raised about readability, backwards-compatibility, the ability to add default template arguments to existing templates, and so on, that caused us to conclude that this would be a bad idea without an explicit sigil requesting deduction.

In Evolution we discussed allowing an opt-in to deduction with a syntax like

  Agg<long, @> agg{1, 2.0};

... but the tricky part is deciding what concrete syntax should replace the @ here. This decision can't really be made in isolation: it has a bearing on the syntax of pattern matching and on concepts, and it was too late to design something new for this at Oulu. (There are a lot of possibilities, and they have different trade-offs and drawbacks.)

Zhihao Yuan

unread,
Jul 11, 2016, 9:59:45 PM7/11/16
to std-pr...@isocpp.org
On Mon, Jul 11, 2016 at 8:22 PM, Richard Smith <ric...@metafoo.co.uk> wrote:
>
> In Evolution we discussed allowing an opt-in to deduction with a syntax like
>
> Agg<long, @> agg{1, 2.0};
>
> ... but the tricky part is deciding what concrete syntax should replace the
> @ here. This decision can't really be made in isolation: it has a bearing on
> the syntax of pattern matching and on concepts, and [...]

And it's questionable whether people want to use this
form... Thanks for the explanations.
Reply all
Reply to author
Forward
0 new messages