std::get<1>(tup);
I would like to be able to type this instead:
std::get(1; tup);The initial motivation is simply to make some metaprogramming look more "function-like":
is_same<T, U>{}
could become
is_same(T, U;)
It will save a few characters, and could cut down on some ambiguities around '<'/'>' for 'less than'/'greater than'.
which is more readable as T and U really are intended as the arguments to that (meta-)function
I've put a short little document on github, I'll try to incorporate feedback into this:
https://github.com/aaronmcdaid/semicolons.and.template.args/blob/master/README.md
Also, I like thisauto v = vector<int>(5); // current form auto v = vector(int; 5); // new form
andauto v = vector<int>{2,3,5,7}; // current form auto v = vector{int; 2,3,5,7}; // new form
Aaron
--
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.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/966bdc02-5921-4274-8fc9-94bb468127e5%40isocpp.org.
Instead of having to type
std::get<1>(tup);
I would like to be able to type this instead:
std::get(1; tup);The initial motivation is simply to make some metaprogramming look more "function-like":
is_same<T, U>{}
could become
is_same(T, U;)
On Friday, October 13, 2017 at 2:13:56 PM UTC-7, Aaron McDaid wrote:Instead of having to type
std::get<1>(tup);
I would like to be able to type this instead:
std::get(1; tup);The initial motivation is simply to make some metaprogramming look more "function-like":
is_same<T, U>{}
could become
is_same(T, U;)
It's not even any shorter! So this is a total non-starter; please don't pursue it any further.
auto v = []<size_t I>() {}
v.operator()<X>(); //only solution now
v<5>(); //not possible to parser as '<' might be an inferior operator
v(5;); //with that proposal
//v is a an argument of a templated function
v.template operator()<X>(); //template keyword required here to avoid '<' to be interpreted as an inferior sign
func!(42)("hello");
std::get!(1)(t);
func!(42; "hello");
std::get!(1; t);
func!(42: "hello");
std::get!(1: t);
auto v = []<size_t T>() {};
v!(42);
You suggest that, like D, we could use something like '!' to introduce the template args. Currently, the C++ compiler has to do lookups on types and check whether a particular name is dependent before it can decide whether a given '<' might have a matching '>'. Under this proposal, the presence of a ':' would clearly demonstrate that the preceding arguments are template arguments and therefore parsing would be relatively simple, even without a '!'. This parsing could complete without any of the special semantic analysis that is currently required by C++
A::template func<int>(); //"template" placed before 'func' to inform the compiler that what follows is a template and to use the template-id rule instead of the normal one.
auto v = []<class T>(int = 0) {};
v!(int);
v!(int; 42);
v!<int>(); // `!<` token sequence need always `>`
v!int(); //parsed as `(v!int)();` not `v!(int())`
v!(int)(); //same as D
If we use `!` then why do not use exactly same syntax as D? or at least more C++-like version with `<`?
v!<int>(); // `!<` token sequence need always `>`
v!int(); //parsed as `(v!int)();` not `v!(int())`
v!(int)(); //same as D
I'm happy to switch to a colon ':' instead of a semicolon ';'. From a parsing point of view, my understanding is they are both suitable in this proposal
I forgot that statement exprs (which are likely to be standardized) have to be enclosed in braces as well as parentheses (and, more foolishly, that switch labels are preceded with case), but there still is a possible ambiguity with semicolons (besides the GNU extension for predeclaring length arguments for VLAs): If foo names both a type and an object, whether ({foo;}) is a size-0 initializer_list<foo> or a size-1 initializer_list<decltype(foo)>.
Ray
When using Templates, we are allowed to declare both Type as well as Non-Type Parameters.
This is not the case for Functions. Allowing functions to declare type parameters, as well as constexpr non-type parameters would end a long history of inconsistencies at once:
Templates were initially intended to make containers parameterizable, not to perform compile time computations or computation on types (See Stroustroup [2]).
std::get<1>(tup)
In order to return the nth value from a tuple, std::get needs this number as a parameter.
That means -
mathematically speaking - std::get is a function just like operator[](int) is one.
is_same<T, U>{}
is also a function on types (mathematically speaking) and should be invoked as such:
constexpr bool = is_same( T , U );
However, if types were made functional at all, we should rather have a built-in operator== for them.
v.operator()<X>()
same thing applies here...
constexpr typename add_pointer( typename t ){ return t*; }
// in code
add_pointer( int ) hello; // Is this what a variable declaration looks like? Probbaly no.
template<class T> using add_pointer = t*;
constexpr(true) auto operator[](size_t i) { std::get<i>(*this); } //compile-time only function, no assembly can be produced.
//The result and the arguments are forced to be constexpr or else compile error
std::tuple t = {...};
t[42];
make_shared<foo>(1, "two", 3.0);
make_shared(foo ; 1, "two", 3.0);
make_shared(foo : 1, "two", 3.0);
If we're in a context where commas would separate function args (as opposed to merely being the comma-operator), then we'll allow to insert template args just after the opening parenthesis with a (semi-)colon after them.
make_shared!(foo : 1, "two", 3.0);
make_shared!<foo >( 1, "two", 3.0); // waste of characters, why use ">(" instead of ":"
Thanks Bastien for giving another example where '<' is confusing to the compiler and where a new syntax might help.
A::template func<int>(); //template required because name lookup not possible
A::func!(int;);
A::func!(int);
BTW this syntax is ambiguous - distinguish between call with template-only arguments and value-only arguments. Using multiple parens is also undecidable in case return object is callable. From my experience, there's already very little need to specify function template arguments explicitly. Even less with deduction guides. Let's not make language even more complex.
I'll restate the initial proposal, as the last couple of comments have shown that this thread has gone off topic significantly.
Instead of writing
make_shared<foo>(1, "two", 3.0);
I propose to be able to write
make_shared(foo ; 1, "two", 3.0);
instead. Or perhaps, as have been suggested, we'll use `:` instead of `;`
make_shared(foo : 1, "two", 3.0);
Slightly more clearly:If we're in a context where commas would separate function args (as opposed to merely being the comma-operator), then we'll allow to insert template args just after the opening parenthesis with a (semi-)colon after them.
Let's clear up a few basic things first. There is no ambiguity issue. There is no valid code which would change meaning under this proposal. Yes, it is true that `:` also has meaning in the language already as part of a `case` and inside `b ? t : f` expressions, but the compiler can trivially identify those two cases easily already. This is an addition to the grammar, and not overly complex either.
This saves one character on the status quo, `(:)`, versus `<>()`. And it saves having to type `template` in some instances.
Of course, it would still involve work for compiler implementors and tools generally (like text editors). I'm not saying it's the most trivial thing ever. But it is much simpler than the `<` and `>` currently used. For example, when a current compiler sees this:
auto x = baz(foo<bar,
it is potentially very confused. Is the `<` opening a template or a 'less-than' operator? Is the `,` separating template args for `foo` or is it separating normal arguments for `baz`?
Parentheses, `(`, and braces, `{`, (and also brackets, `[`) have the advantage that they always group in a simple way, which is why I'm relying on parentheses in my proposal. In this proposal, a comma (and `:` or `;`) is trivially associated with its enclosing parenthesis and therefore the compiler can do a lot of parsing relatively easily.
So the question is - assuming we want to change from status quo - how many characters are we willing to spend on making things easier for the compiler?
At the expense of one more character (and therefore equivalent to the status quo), we could introduce a `!`.
make_shared!(foo : 1, "two", 3.0);
With the `!` like this, I would still like to use `:` to separate the two "kinds" of args from each other, because this still uses one fewer character than:
make_shared!<foo >( 1, "two", 3.0); // waste of characters, why use ">(" instead of ":"
Of course, maybe nobody is interested. But if there is a problem with my proposal, I would like a more concrete example of real code where parsing would be made more difficult than current code.
... please don't make such a beautiful programming language so ugly.
make_shared(foo : 1, "two", 3.0);
--
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.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/05334640-3e48-4b67-aee8-a511ec6d62a0%40isocpp.org.
--
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.
To post to this group, send email to std-pr...@isocpp.org.
Extremely ugly. At the moment there is an extremely clear easy-to-spot distinction between templates and parameters. This is great because they are completely separate things with completely different behaviour and completely different meaning. In longer function declarations you can do some nice indentation.The proposal is to bundle the two together in two lists separated by a symbol that looks very similar to a comma. I'm not saying this is going to be a root cause of eye strain amongst C++ developers, but this makes the language more awkward to LOOK at, which is something developers tend to do a lot. Indentation becomes a nightmare.It will require some really funky code to refer to types unless we want two versions of the notation flying around. I don't even want to imagine the circle of hell the proposal's impact on functions pointers/std::functions would belong in. How does the compiler or even the reader tell the difference between a reference to a function and a call of it if we place everything in parentheses? Especially if the parameters have defaults.What we have is a major piece of ugly code in very specific situations where a template (or, should I say, the use of operator<X>()) doesn't even make sense in the first place. Operator overloads are a nice convenience. Templates are a nice convenience. Put the two together mindlessly and you're asking for trouble, but that's the nature of the operator conveniences and always has been.So yes, this proposal - and the suggested modifications to it - are ugly, confusing, and even potentially discriminatory to those with minor vision problems (... or dead pixels).
template<size_t sz>
void foo(std::integral_constant<sz>)
{
//Use sz, not the function parameter.
}
foo(10_const);
On Thursday, December 21, 2017 at 12:56:28 PM UTC-5, Jake Arkinstall wrote:
Extremely ugly. At the moment there is an extremely clear easy-to-spot distinction between templates and parameters. This is great because they are completely separate things with completely different behaviour and completely different meaning. In longer function declarations you can do some nice indentation.
The proposal is to bundle the two together in two lists separated by a symbol that looks very similar to a comma. [...]It will require some really funky code to refer to types unless we want two versions of the notation flying around. [...]Here's the thing though. As C++ has developed, the distinction between template parameters and non-template parameters has become increasingly blurred. [...]
The OP's feature is essentially asking us to be able to do away with the pretense. To get rid of the `_const` noise and be able to treat template arguments like function arguments. The use of a semicolon is merely to appease the syntactic needs of C++, since there still is a distinction between the two.But as that distinction breaks down, the need for this feature increases.Personally, `constexpr` parameters make far more sense than doing it with this syntactic distinction.
Here's the thing though. As C++ has developed, the distinction between template parameters and non-template parameters has become increasingly blurred. It began in C++98/03, when we got function template argument deduction: the ability to deduce template parameters from non-template parameters. In most cases, there were deducing type template parameters.
C++11 gave us constexpr functions. With the right tools, this allows us to provide non-type template parameters through deduction:
template<size_t sz>
void foo(std::integral_constant<sz>)
{
//Use sz, not the function parameter.
}
foo(10_const);Where `_const` is a UDL that generates an `integral_constant`.The OP's feature is essentially asking us to be able to do away with the pretense. To get rid of the `_const` noise and be able to treat template arguments like function arguments. The use of a semicolon is merely to appease the syntactic needs of C++, since there still is a distinction between the two.But as that distinction breaks down, the need for this feature increases.Personally, `constexpr` parameters make far more sense than doing it with this syntactic distinction.
On 21 Dec 2017 18:14, "Nicol Bolas" <jmck...@gmail.com> wrote:Here's the thing though. As C++ has developed, the distinction between template parameters and non-template parameters has become increasingly blurred. It began in C++98/03, when we got function template argument deduction: the ability to deduce template parameters from non-template parameters. In most cases, there were deducing type template parameters.C++11 gave us constexpr functions. With the right tools, this allows us to provide non-type template parameters through deduction:
template<size_t sz>
void foo(std::integral_constant<sz>)
{
//Use sz, not the function parameter.
}
foo(10_const);Where `_const` is a UDL that generates an `integral_constant`.The OP's feature is essentially asking us to be able to do away with the pretense. To get rid of the `_const` noise and be able to treat template arguments like function arguments. The use of a semicolon is merely to appease the syntactic needs of C++, since there still is a distinction between the two.But as that distinction breaks down, the need for this feature increases.Personally, `constexpr` parameters make far more sense than doing it with this syntactic distinction.This makes sense to some extent, and partially knocks down one of my two main concerns (that the template parameters and function parameters are two different concepts - the other is syntax, as suggestions thus far are the textual equivalent to green text on a red background).The remaining concerns I have about the template parameter / function parameter distinction are as follows.First of all, contexpr functions are only useful in this case for inputs known at compile time. We can never keep the benefits of templates whilst also allowing general arguments in.
template<typename ...Args>
constexpr auto &get(constexpr size_t ix, tuple<Args...> &tpl)
{
constexpr auto offset = tuple<Args...>::_GetOffset(ix); //Guaranteed constexpr call.
void *ptr = static_cast<tuple_element_t<tuple<Args...>, ix>(tpl._GetPtrFromOffset(offset));
}
What is the workaround - generating template versions of the functions and non-template versions? Will it not simply cause more confusion if we have to explain to people why the first half of a function call can not be some constexpr function evaluated on post-compilation input?
To me, the contexpr is a step in a very useful direction, but I don't see this being the logical outcome.Secondly, what does this say about types as template parameters, which are somewhat less flexible than values?
Thirdly, are we restricting this to mere function calls or are we talking about the possibility of declarations too?
Because I have no idea how sfinae is supposed to be handled here, and we would need to still have the ability to use templates as they are for backwards compatibility - and two syntaxes for the same thing smells familiar *cough* trigraphs *cough*What I propose is what I think should always have been done for trigraphs. Have a preprocessing program that parses the proposed style into current C++ code to be input to the compiler. We're talking about a handful of regular expressions, perhaps using the long form of function calls every time or just when necessary. Allow code to be written in this way but still have it easy to convert and utilise by everyone else for now. Once there exists a community of people comfortable using it, it would be a lot easier to get by the standards committee, in the same vein as Boost.
--
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.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/f67e981b-3ffb-4a8f-9444-d237c93238e4%40isocpp.org.