// driver
struct SpecializationDriver
{
constexpr SpecializationDriver(const meta::template_template_decl& templateTemplateDecl,
const meta::template_decl& templateDecl)
: result(templateTemplateDecl.getName() == templateDecl.getName()) { }
constexpr bool result;
};
template<template <class...> class Template, class T> $use(SpecializationDriver driver)
bool is_specialization_of()
{
return driver.result;
}
int main()
{
std::cout<< is_specialization_of<std::tuple, std::tuple<double>>() <<::std::endl;
std::cout<< is_specialization_of<std::vector, std::tuple<double>>() <<::std::endl;
std::cout<< is_specialization_of<std::array, std::tuple<double>>() <<::std::endl;
return 0;
}std::array<class,int>`.std::array<class,int>.On 1/7/14 10:17 AM, Richard Smith wrote:This idea is unscalable if the ? represents a particular template parameter list. If there were two template template parameters with different lists, you would end up attempting to assign both to ? .
Rather than introducing a new keyword, you could use a '?' token:
template<template<? ...> class A, ? ... Ts> void f(A<Ts...>);
(or a '*' token, or something similar).
I'm pretty sure I wrote something about the issue on this board a while ago, but can't recall the details.
A bare ellipsis seems to make it clearer that there is no underlying storage or meta-variable.
template<template<...> class A, ... Ts> void f(A<Ts...>);
In this case, the template parameter list of A and the argument types/kinds of Ts are deduced separately, and conversion potentially occurs when forming A<Ts...> . No expressiveness is lost versus the "?" syntax because names at the call site are determined to refer to types or objects independently of the template parameter list, so ? would not pass any information back to the user anyway.As for the non-type role, that sounds nice as a separate proposal. The standard explicitly mentions that it's impossible to pass a non-type argument and deduce its type, and it makes usage of e.g. std::integral_constant repetitive.
The 'auto' keyword would make sense here, but it might make more sense
being restricted to a non-type template parameter (with its type deduced
from the template argument). Perhaps it could be made to fill both roles:
Looks like a solution in search of a problem. Every use of the parameter would have to be disambiguated, and since the parameter can only refer to the typename or object passed by the caller, each disambiguation would have to go the same way. Might as well keep the status quo.
template<auto X> void f() {
int a = X; // it's a value by default
}
template<auto X> void g() {
typename X y; // it can be explicitly treated as a type
}
template<auto X> void h() {
template X<int> z; // or as a template
}
template<auto &X> void i(); // not exactly 'auto', always a non-type
template parameter
... though this would require a lot of hacking with the grammar, to allow
'template' and 'typename' in these new places.
I agree that something like your ? is needed to be able to disassemble the list of template arguments.We would also need some way to overload based on whether the "head", i.e. your ?X is a type or a value. Maybe this can be done with partial class template specialization already with the aid of SFINAE but what we need to boil it down to is:is_type<?X>::value to be true or false depending on if X is a type or a value.If it is not a type we also need to know the type of the value, which I imagine can be done with decltype(X) iff X is not a type.
To make sure that we don't use this decltype erroneously we would have to specialize helper templates on is_type<?X>::value in the regular template programming style unless we get a static if so that a more imperative style can be used.Here is a try at implementing is_type:// Base declaration;template<?X> struct is_type;// Specialization for typename:template<> struct is_type<typename X> { static const bool value = true; }template<typename T> is_type<T X> { static const bool value = false; }Does this make any sense? I'm very uncertain about the empty <> in the first specialization, is it logical at all?
Whatever solution can be found to this detail it is important that it can be done, it is nice if it can be done without introducing any more language features than the ? itself. It is also good if such a trait would be added to the standard library to avoid having to invent it over and over.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
On 1/9/14 8:44 AM, Richard Smith wrote:
> Here's an implementation:
>
> template<? X> struct is_type : std::false_type {};
> template<typename T> struct is_type<T> : std::true_type {};
This appears to be using ? like auto, not to mean "type or object."
Also, as you know, class templates cannot currently be overloaded like
this.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
On 1/9/14 10:41 AM, Richard Smith wrote:
It's not an overload, it's a partial specialization.
OK, that wasn't clear from the example. So do you intend that an identifier declared with "?" never be used? What could you possibly do with X?
Quoting the previous message:Edit: You couldn't even use X in these cases, because parse time ambiguity of a template argument is always resolved in favor of a typename ([temp.arg] §14.3/2).
I still don't see the value of an identifier, as opposed to a pack
expansion element, that can be either a type or a value. And such a name
would throw a wrench into template parsing. They could *only* be used as
explicit template arguments to functions as in my example above, or to
template template parameters with "?"-like parameter lists.
If you end up needing to use is_type, you're already in deep shit.
On the other hand, parameter lists are already unpacked using
overloading, or partial specialization which works the same way. This
gives you a branching point to different code paths for type, value, or
template, which can already be written and parsed without redesigning
dependent name lookup.
This is why I think "..." is sufficient with no motivation for "?" or
any provision for a single argument.
On 1/10/14 8:11 AM, David Krauss wrote:I should be more specific.
On 1/9/14 11:18 AM, Richard Smith wrote:
The useful thing about introducing a new feature is that you get to specify
how it works =) Naturally, we would specify that passing a generic template
argument to another template preserves the kind of template argument.
But how can you make that work without redoing how parsers must classify type-dependent expressions? And what's the benefit, given that overloading/partial specialization already solve the problem?
Given "?", you can peel off a fully-generic argument from a pack, and pass it to another template. But the other template must be either fully-generic, or overloaded/partially specialized. So you might as well peel the pack in the target overloaded/partially specialized template. All "?" buys you is the freedom to add a dispatcher between components which are actually necessary.
template<...> struct HeadInfo;template<typename T, ...> struct HeadInfo<T, ...> {static const bool is_type = true;typedef T type;};template<auto V, ...> struct HeadInfo<V, ...> {static const bool is_type = false;typedef decltype(V) type;static const auto value = V;};
template<typename T, ...Tail> struct HeadInfo<T, Tail...> {
static const bool is_type = true;typedef T type;};
template <...> struct A {};template <class T, class U>struct B;template <...ElemsT, ...ElemsU>struct B<A<ElemsT...>, A<ElemsU...>>{};
Yes, you are absolutely right, the "Tail" should have been there in my example just as you wrote it.So it seems right now that we can make do with the ... "generic pack" type and auto, but it bugs me a bit that we now have all of these forms of a template parameter type (where int is of course just an example):int One template parameter of type intint... Any number of int template parametersauto One non-type template parameter of any typeauto... Any number of non-type template parameters of mixed types*typename One type template parametertypename... Any number of type template parameters
... Any number of type or non-type template parametersBut not:? One type or auto tempalte parameter (apart from the bikeshed issue of ?)At least from an educational standpoint it could be wise to be more orthogonal, which would also mean to reintroduce ?... instead of just ...Another risk I see with using ... is that people will start to over-use it because it looks nice, i.e. writing template<...> for a variadic template template parameter even when the code only handles that the actuals are types.In the back of my head I also feel that sooner of later we will find something that can't be done due to the omission of the lonely ? feature.Entering the bikeshed I toyed with the use of . instead of ? It kind of goes nicely with ... as it would be interpreted as "many dots". The main problem could be that it is almost invisible on the screen especially as a typical usage would be template<. H,... T>. The * suggested in this thread is a bit scary as you can also write for instance template<int*...> which as another traditional meaning... I also scanned the keyword list but didn't find any real candidates.
BTW: I can't seem to find any wording in the standard document (C++14) that allows for instance a function taking any number of ints, although I have seen uses of it in this list (and which I assumed was available in my list above):template<int... dims> class Matrix;VS2012 also does not allow this. What is the status?
* The reason for assuming that auto... would refer to any number of parameters of different types is that otherwise reursive decomposition like this would be strange:template<auto H, auto... Ts> class Foo;as now H is "another auto" than Ts which can bind to another type, while the Ts must still be the same, untill next recursion step.Is there a paper or thread for auto template parameters?
Den fredagen den 10:e januari 2014 kl. 16:35:15 UTC+1 skrev Alex B:On Friday, January 10, 2014 5:01:31 AM UTC-5, Bengt Gustafsson wrote:template<...> struct HeadInfo;template<typename T, ...> struct HeadInfo<T, ...> {static const bool is_type = true;typedef T type;};template<auto V, ...> struct HeadInfo<V, ...> {static const bool is_type = false;typedef decltype(V) type;static const auto value = V;};That syntax without ? would still require being able to name the generic pack. Your example should be:template<typename T, ...Tail> struct HeadInfo<T, Tail...> {static const bool is_type = true;typedef T type;};Giving a name would be required to disambiguate cases where there is more than one generic pack:template <...> struct A {};template <class T, class U>struct B;template <...ElemsT, ...ElemsU>struct B<A<ElemsT...>, A<ElemsU...>>{};As for actual use cases (with or without ?), there is more than metaprogramming refactoring sugar. I can see at least one case that it would allow to fix which is boost recursive variants:Unless I'm wrong, recursive variants currently cannot contain a template type with non-type parameters, which is a bit annoying. This feature would make it possible.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.