Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to deduce alias templates to template template parameter while still preserving its property of being deduced context

After a while I discovered again a power of template template-parameters. See e.g. the following snippet:

template <template <class> class TT, class T>
void foo(TT<T>) {
}

template <class T>
using typer = T;

int main() {
    foo<typer>(int{});
}

The alias template is passed to the template as a template template-parameter and is used further to detect the other parameter of the template as it is deduced context. Beauty!

However just when the alias template itself need to be deduced it looks like the compilers get crazy:

template <template <class> class>
struct tag{};

template <template <class> class TT, class T>
void foo(tag<TT>, TT<T>) {
}

template <class T>
using typer = T;

int main() {
    foo(tag<typer>{}, int{});
}

[live demo]

Compilers of course are right as TT can be deduced from both tag<TT> as well as TT<T> parameters of foo, and the int{} doesn't match the template template with type parameter pattern. Is there any way to preserve the deduction context for T but make TT non-deduced context in TT<T>?

P.S. My intentions are pure and this is just a theoretical question with no Y problem behind it.

like image 562
W.F. Avatar asked Oct 08 '17 11:10

W.F.


People also ask

What is template argument deduction?

Template argument deduction is used in declarations of functions, when deducing the meaning of the auto specifier in the function's return type, from the return statement.

Can a template be a template parameter?

A template argument for a template template parameter is the name of a class template. When the compiler tries to find a template to match the template template argument, it only considers primary class templates. (A primary template is the template that is being specialized.)

Can we pass Nontype parameters to templates?

Template classes and functions can make use of another kind of template parameter known as a non-type parameter. A template non-type parameter is a template parameter where the type of the parameter is predefined and is substituted for a constexpr value passed in as an argument.

Why do we use template template parameter?

8. Why we use :: template-template parameter? Explanation: It is used to adapt a policy into binary ones.


1 Answers

I think it would be easier/clearer to write something like:

template <template <class> class TT, class T>
void foo(tag<TT>, T, std::enable_if_t< std::is_same<T,TT<T>>::value >* = 0 )

or the less constrained

template <template <class> class TT, class T>
void foo_impl( tag<TT>, TT<T> ){}

template <template <class> class TT, class T>
void foo( tag<TT> a, T b ){ foo_impl<TT>( a, b ); }

as a side note, this shows that the (non normative) note in the standard claiming that An alias template name is never deduced is somewhat inaccurate ...

like image 104
Massimiliano Janes Avatar answered Sep 20 '22 08:09

Massimiliano Janes