Make aliased templates first class citizens

111 views
Skip to first unread message

adrian....@gmail.com

unread,
Dec 17, 2017, 7:21:12 PM12/17/17
to ISO C++ Standard - Future Proposals
Templates are wonderful idea, but if I need to make a template with partially defined parameters, this becomes problematic, requireing that an intermediate class is made with a template in it.  Because the template then becomes a dependent type, we then have to declare the word template before it's name if you pass it, which is ugly and sometimes difficult to track down what is wrong when you get the syntax incorrect.

Complete template aliasing is available in the language like this:

 template <typename FROM, typename TO>
 
using my_is_convertable = std::is_convertable<FROM, TO>;

I propose that partial template aliasing also be allowed, which would allow the template be broken up in to 2 or more sub-templates.

For example, say I have a find meta-algorithm, which will have a value that is true if any of OP<Ts>::value... are true or false otherwise.  I will only declare it here for brevity.

 template <typename <typename> class OP, typename...Ts>
 
struct find;

It is defined as a unary template operator to apply the DRY principal.  Now if I want to use this on a binary template operator, then I would need to bind the parameter.  If known ahead of time, it would become:

 template <typename TO>
 
using my_is_convertable = std::is_convertable<int, TO>;

and would be used like so:

 find<my_is_convertable, float, int, double>::value

However, if it's not known ahead of time what to bind the parameter to I would have to use an class template with a embded template alias in it like this:

 template <typename FROM>
 
struct my_is_convertable
 
{
   
template <typename TO>
   
using ttype = std::is_convertable<FROM, TO>;
 
};

And use it like this:

 find<my_is_convertable<int>::template ttype, float, int double>::value

I propose that instead we use this syntax to define partial template aliasing:

 template <typename TO>
 
template <typename FROM>
 
using is_convertable = std::is_convertable<TO, FROM>;

 find
<my_is_convertable<int>, float, int double>::value

This would also make this valid:

 my_is_convertable<int><int>::value

Which should be fine.

Pros:

Verbosity is lowered, no more need for referring to an embedded template is required which follows that the need for the template keyword is also removed, all of which reducing noise.  Also it would not break anything in the wild.  This would also mostly remove the need for tbind, except in cases where symbol leakage is not wanted in the enclosing scope.  

Cons:

Developers would need to get used to the syntax.  Nothing too crazy though.  

What is everyone's opinion on this?

inkwizyt...@gmail.com

unread,
Dec 17, 2017, 8:18:29 PM12/17/17
to ISO C++ Standard - Future Proposals, adrian....@gmail.com
Right now I see only one problem with this:
template<typename A>
using B = typename A::template template temp<1><2>;
//or
template<typename A>
using C = template A::template temp<1>; //this return template not type, this could be problematic when C++20 remove options for different `using`
//or
template<typename A>
using D = template template A::temp;
You will probably need something like this to allow proper handle of `<` and `>` by compiler in dependent context.

adrian....@gmail.com

unread,
Dec 18, 2017, 12:28:12 AM12/18/17
to ISO C++ Standard - Future Proposals, adrian....@gmail.com
On Sunday, December 17, 2017 at 8:18:29 PM UTC-5, Marcin Jaczewski wrote:

Right now I see only one problem with this:
template<typename A>
using B = typename A::template template temp<1><2>;
//or
template<typename A>
using C = template A::template temp<1>; //this return template not type, this could be problematic when C++20 remove options for different `using`
//or
template<typename A>
using D = template template A::temp;
You will probably need something like this to allow proper handle of `<` and `>` by compiler in dependent context.

I'm not exactly sure what you mean.  So, these are potential ways to tell the compiler what it should be seeing?  temp is a binary operator?  What is A?  Could you please give more context or explain in more detail what you are attempting to say?

inkwizyt...@gmail.com

unread,
Dec 18, 2017, 3:56:37 PM12/18/17
to ISO C++ Standard - Future Proposals, adrian....@gmail.com
What is `temp`? This is good question that your proposal should answer because it's dependent name on template parameter `A`. If we implements your proposition how you will access it if it is in dependent context?
Right now we have way to distinguish between objects, types and templates, now with your proposal we will need new way to support your first class aliases.

Jack Adrian Zappa

unread,
Dec 19, 2017, 8:47:55 AM12/19/17
to ISO C++ Standard - Future Proposals, adrian....@gmail.com
Ah, sorry.  Not sure how I misread that.  If I understand the current parsing of C++, I think your 1st one is most appropriate.  Also, could you expand on what you mean by your 2nd item being possibly problematic in c++20? 

inkwizyt...@gmail.com

unread,
Dec 19, 2017, 9:32:05 AM12/19/17
to ISO C++ Standard - Future Proposals, adrian....@gmail.com
Last one is similar in functionality to your declaration:
template<int I>
template<int J>
template<typename A>
using B = typename A::template template temp<I><J>;

template<typename A>
using C = template template A::temp;

One difference is that in my case we would not need what template parameters are needed for `temp`

For 2nd I referring to http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0634r0.pdf now depending what syntax you will want use this proposal will or will not affect it. This it simply thing to consider when you are choosing syntax for this proposal.

Mingxin Wang

unread,
Dec 21, 2017, 9:14:15 AM12/21/17
to ISO C++ Standard - Future Proposals
As far as I am concerned, this feature could be mainly used on specifying template arguments in separated semantic levels.

On the one hand, I think the motivation of this idea is probably not sufficient enough for a core language feature. After all, this is a pattern in compile-time programming and could be easily implemented with struct templates (as illustrated in the initial post), and I did not see the peculiarities of this pattern so that it need support at the language level.

On the other hand, as other feedback reports, this feature introduces a new language-level concept - template of template, which is at the same level as the concepts of "types" and "type templates". If this concept is standardized, a number of clauses may be reappraised. For example, should "template of template" be a valid template argument type? Is it allowed to declare a type or function template with templates in multiple layer?

Actually, I have handled some cases that required specifying a type template in multiple separated semantic levels, and I found it acceptable to design a helper struct (or class) template as a "configurator", e.g.:

template <class T, class Alloc, std::size_t SOO>
class Aaa; // requires concept Bbb

template <class Alloc, std::size_t SOO>
struct AaaConfigurator {
  template <class T>
  using type = Aaa<T, Alloc, SOO>;
};

template <template <class> class BbbTemplate>
class BbbUser;

template <class Alloc = DefaultAlloc, std::size_t SOO = alignof(std::max_align_t)>
using AaaUser = BbbUser<AaaConfigurator<Alloc, SOO>::template type>;

Mingxin Wang
Reply all
Reply to author
Forward
0 new messages