Relaxing requirements on template template parameter matching.

135 views
Skip to first unread message

Bengt Gustafsson

unread,
Sep 1, 2015, 11:57:03 AM9/1/15
to ISO C++ Standard - Future Proposals
Today a template template parameter can only be matched by a template class with exactly the same set of template parameters. Default parameters or variadic parameters are ignored.

Example:

template<template<typename> class TPL> class X {
 TPL
<int> mVar;
};

template<typename A, typename B = int> struct Y {
};

X
<Y> fee;   // ERROR: Y has too many template parameters, even though one has a default.

template<typename... Ts> struct A {
};

X
<A> foo;    // ERROR: A has wrong template parameters, although A can be instantiated with one type, just as X will do.


Does anyone know what the rationale is behind this restriction?

One problem this would solve is that today if you want to be able to replace a container which could default to std::vector, the replacement container must also have two template parameters (the second being the allocator).

Another problem it would solve is that you actually have to know that vector has two template parameters and basic_string has three when modelling a template template parameter where they are to be possible candidates.

The other problem is that this rule forbids the designers of the standard library to generalize class templates by adding more template parameters with defaults, as some developer out there may have used the
class template in a template template parameter situation.

This argument was used against me when I suggested that std::array could be made n-dimensional like this:

template<typename T, size_t... dims> class array;

NO NO: That's not backwards compatible, what if someone has done this:

template<template<typename T, size_t> class> class ArrayHolder {};

ArrayHolder<std::array> my_holder;  // Breaks with new std::array definition...

David Krauss

unread,
Sep 1, 2015, 1:13:36 PM9/1/15
to std-pr...@isocpp.org

On 2015–09–01, at 11:57 PM, Bengt Gustafsson <bengt.gu...@beamways.com> wrote:

Does anyone know what the rationale is behind this restriction?

As far as I know, it’s the only way to count the number of parameters in a class template.

The priorities are backwards, but compatibility inertia is pretty strong.

Note that alias templates can provide the illusion that classes like vector and basic_string have only one parameter.

template< typename t >
using univec = std::vector< t >;

template< typename t >
using unistring = std::string< t >;

These aliases can be used as default arguments to template template parameters.

Christof Meerwald

unread,
Sep 1, 2015, 3:05:30 PM9/1/15
to std-pr...@isocpp.org
On Tue, Sep 01, 2015 at 08:57:03AM -0700, Bengt Gustafsson wrote:
> Today a template template parameter can only be matched by a template class
> with exactly the same set of template parameters. Default parameters or
> variadic parameters are ignored.
>
> Example:
>
> template<template<typename> class TPL> class X {
> TPL<int> mVar;
> };
>
> template<typename A, typename B = int> struct Y {
> };
>
> X<Y> fee; // ERROR: Y has too many template parameters, even though one
> has a default.
>
> template<typename... Ts> struct A {
> };
>
> X<A> foo; // ERROR: A has wrong template parameters, although A can be
> instantiated with one type, just as X will do.
>
>
> Does anyone know what the rationale is behind this restriction?

The current rules are actually pretty much the opposite of what you
would expect, see
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2555.pdf for
some explanation (and yes, it does seem to be kind of backwards - but
I am not sure if there is a way to make both use cases work...)


Christof

--

http://cmeerw.org sip:cmeerw at cmeerw.org
mailto:cmeerw at cmeerw.org xmpp:cmeerw at cmeerw.org

Bengt Gustafsson

unread,
Sep 2, 2015, 3:41:53 AM9/2/15
to ISO C++ Standard - Future Proposals, cme...@cmeerw.org
@Cristof: I don't see the connection. AFAIK what is described in N2555 currently is in the language, you can do this:

template<template<typename...> TPL, typename... Us> class X<TPL<Us...>> {};

What I was talking about is to be able to supply a variadic template class when a n-ary is asked for, basically. (And similarly one that has additional, but defaulted parameters).

@David:

I understand your answer to mean: "Someone has likely used this (mis)feature to check how many template parameters a template has, typically in some SFINAE situation". The using trick can save the day in some situations, I guess.

Gien the above it seems that this proposal is not possible to do. Thanks for the clarification! It is a pity though that this prevents some nice "upgrades" of existing class templates, forcing the invention of new (probably less and less obvious) names in the std namespace.

Christof Meerwald

unread,
Sep 2, 2015, 3:59:57 AM9/2/15
to std-pr...@isocpp.org
On Wed, Sep 02, 2015 at 12:41:52AM -0700, Bengt Gustafsson wrote:
> @Cristof: I don't see the connection. AFAIK what is described in N2555
> currently is in the language, you can do this:
>
> template<template<typename...> TPL, typename... Us> class X<TPL<Us...>> {};

You could do that before N2555 already.

> What I was talking about is to be able to supply a variadic template class
> when a n-ary is asked for, basically. (And similarly one that has
> additional, but defaulted parameters).

Well, what you want to do is:

namespace ns1
{
template<template<typename> class TT>
struct A
{ };

template<typename ... T>
struct B
{ };

A<B> a;
}

And this is what N2555 says you can do at the moment (which is pretty
much the other way around of what you want):

namespace ns2
{
template<template<typename ...> class TT>
struct A
{ };

template<typename T>
struct B
{ };

A<B> a;

Arthur O'Dwyer

unread,
Sep 2, 2015, 9:14:53 PM9/2/15
to ISO C++ Standard - Future Proposals, cme...@cmeerw.org
Digression: notice that even under the current standard you cannot do this variation:

namespace ns2
{
 
template<template<typename ...> class TT>
 
struct A
 
{ };


 
template<typename T, int J=0> // here I've added a non-type template parameter with a default value
 
struct B
 
{ };

  A
<B> a; // fails to match
}

There has been discussion on this list within the past year of whether and how to support "template parameters of unspecified kind"; whether template<auto T> struct X should match both X<int> and X<1>, for example. This would let metaprogrammers support things like

template<???> struct wrap { ... };
wrap
<std::vector, int> wrapv;
wrap
<std::vector, int, std::allocator<int>> wrapv;
wrap
<std::array, int, 3> wrapa;

That seems of limited usefulness, admittedly. 

–Arthur
Reply all
Reply to author
Forward
0 new messages