Discussion:
[std-discussion] An implementation of enhanced auto deduction and abbreviated template syntax using Clang
Faisal Vali
2015-03-04 02:39:47 UTC
Permalink
In the hopes of soliciting constructive feedback, if anyone has the
time or the interest to play with a patched up Clang that implements
enhanced auto deduction & abbreviated template syntax from the
concepts ts, here it is:

https://github.com/faisalv/clang/tree/enhanced-auto-c%2B%2B1z .

The last line of the README file tells you the subversion revision of
LLVM to use.

For examples of test cases that successfully compile, please refer to:
-- https://github.com/faisalv/clang/blob/enhanced-auto-c%2B%2B1z/test/CXX/auto/cxx1z-auto-vars-generalized.cpp
-- https://github.com/faisalv/clang/blob/enhanced-auto-c%2B%2B1z/test/CXX/auto/cxx1z-abbreviated-templates.cpp

I would certainly appreciate the feedback!

1) Enhanced-Auto Deduction:

pair<auto...> f() { return make_pair([] { }, [] { }); }
vector<auto> v = vector<int>();

2) Abbreviated Template Syntax:
void f(auto) <=> template<class T> void f(T);


A few, perhaps not so obvious or interesting, technicalities:

a) The equivalence of templates when it comes to trailing return
types in function pointer parameters is based on the order of the
'auto' that signifies a placeholder, not just the appearance of an
auto in the declaration-specifier of a parameter:

template<class R, class P> void f( R(P) ); // #1
template<class P, class R> void f( R(P) ); // #2 (order of
templ-params flipped)

template<class R, class P> void f( auto (P)->R); // equivalent to
#1, not abbreviated.
void f(auto(auto)); // equivalent to #1
void f(auto (auto) -> auto); // equivalent to #2
// the trailing return type auto
// identifies a
template parameter
template<class R> void f(R(auto); // equivalent to #1
template<class P> void f(auto(P)); // equivalent to #2

b) variadic auto
Once an ellipsis is seen as part of the declarator, all contained
auto placeholders get transformed into parameter packs.
void f(auto (*...)(auto) -> std::tuple<auto, std::pair<auto, auto>...>);
Note there are 4 deducible template parameter packs above.

c) multi abbreviated template declarations
void f(auto), g(auto);
are allowed - the above declares two function templates.

d) template aliases desugar their types *after* each auto has been
identified as a placeholder (and so must be deduced)

template<class T> using Int = int;
Int<auto> i = 3; // Is an error, auto must be deducible.

e) generic lambda's as default arguments work with abbreviated template syntax:
void f(int (*)(int) = [](auto a) { return a; }, auto b = decltype(b){});
f<float*>(); // OK

f) variable templates and enhanced auto deduction interact as expected:
template<class T> pair<auto...> (*vfp)(auto...) = [](T t1, T* t2)
{ return make_pair(t1, t2); };

Thanks!
Faisal Vali
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Gabriel Dos Reis
2015-03-04 03:45:01 UTC
Permalink
Should we declare "auto f(auto) -> auto" an excess in sophism?

-- Gaby
Post by Faisal Vali
In the hopes of soliciting constructive feedback, if anyone has the
time or the interest to play with a patched up Clang that implements
enhanced auto deduction & abbreviated template syntax from the
https://github.com/faisalv/clang/tree/enhanced-auto-c%2B%2B1z .
The last line of the README file tells you the subversion revision of
LLVM to use.
-- https://github.com/faisalv/clang/blob/enhanced-auto-c%2B%2B1z/test/CXX/auto/cxx1z-auto-vars-generalized.cpp
-- https://github.com/faisalv/clang/blob/enhanced-auto-c%2B%2B1z/test/CXX/auto/cxx1z-abbreviated-templates.cpp
I would certainly appreciate the feedback!
pair<auto...> f() { return make_pair([] { }, [] { }); }
vector<auto> v = vector<int>();
void f(auto) <=> template<class T> void f(T);
a) The equivalence of templates when it comes to trailing return
types in function pointer parameters is based on the order of the
'auto' that signifies a placeholder, not just the appearance of an
template<class R, class P> void f( R(P) ); // #1
template<class P, class R> void f( R(P) ); // #2 (order of
templ-params flipped)
template<class R, class P> void f( auto (P)->R); // equivalent to
#1, not abbreviated.
void f(auto(auto)); // equivalent to #1
void f(auto (auto) -> auto); // equivalent to #2
// the trailing return type auto
// identifies a
template parameter
template<class R> void f(R(auto); // equivalent to #1
template<class P> void f(auto(P)); // equivalent to #2
b) variadic auto
Once an ellipsis is seen as part of the declarator, all contained
auto placeholders get transformed into parameter packs.
void f(auto (*...)(auto) -> std::tuple<auto, std::pair<auto, auto>...>);
Note there are 4 deducible template parameter packs above.
c) multi abbreviated template declarations
void f(auto), g(auto);
are allowed - the above declares two function templates.
d) template aliases desugar their types *after* each auto has been
identified as a placeholder (and so must be deduced)
template<class T> using Int = int;
Int<auto> i = 3; // Is an error, auto must be deducible.
void f(int (*)(int) = [](auto a) { return a; }, auto b = decltype(b){});
f<float*>(); // OK
template<class T> pair<auto...> (*vfp)(auto...) = [](T t1, T* t2)
{ return make_pair(t1, t2); };
Thanks!
Faisal Vali
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Faisal Vali
2015-03-04 04:04:36 UTC
Permalink
Post by Gabriel Dos Reis
Should we declare "auto f(auto) -> auto" an excess in sophism?
Truly we must - especially when discussing 'auto-nomy' ;)
Post by Gabriel Dos Reis
-- Gaby
Post by Faisal Vali
In the hopes of soliciting constructive feedback, if anyone has the
time or the interest to play with a patched up Clang that implements
enhanced auto deduction & abbreviated template syntax from the
https://github.com/faisalv/clang/tree/enhanced-auto-c%2B%2B1z .
The last line of the README file tells you the subversion revision of
LLVM to use.
-- https://github.com/faisalv/clang/blob/enhanced-auto-c%2B%2B1z/test/CXX/auto/cxx1z-auto-vars-generalized.cpp
-- https://github.com/faisalv/clang/blob/enhanced-auto-c%2B%2B1z/test/CXX/auto/cxx1z-abbreviated-templates.cpp
I would certainly appreciate the feedback!
pair<auto...> f() { return make_pair([] { }, [] { }); }
vector<auto> v = vector<int>();
void f(auto) <=> template<class T> void f(T);
a) The equivalence of templates when it comes to trailing return
types in function pointer parameters is based on the order of the
'auto' that signifies a placeholder, not just the appearance of an
template<class R, class P> void f( R(P) ); // #1
template<class P, class R> void f( R(P) ); // #2 (order of
templ-params flipped)
template<class R, class P> void f( auto (P)->R); // equivalent to
#1, not abbreviated.
void f(auto(auto)); // equivalent to #1
void f(auto (auto) -> auto); // equivalent to #2
// the trailing return type auto
// identifies a
template parameter
template<class R> void f(R(auto); // equivalent to #1
template<class P> void f(auto(P)); // equivalent to #2
b) variadic auto
Once an ellipsis is seen as part of the declarator, all contained
auto placeholders get transformed into parameter packs.
void f(auto (*...)(auto) -> std::tuple<auto, std::pair<auto, auto>...>);
Note there are 4 deducible template parameter packs above.
c) multi abbreviated template declarations
void f(auto), g(auto);
are allowed - the above declares two function templates.
d) template aliases desugar their types *after* each auto has been
identified as a placeholder (and so must be deduced)
template<class T> using Int = int;
Int<auto> i = 3; // Is an error, auto must be deducible.
void f(int (*)(int) = [](auto a) { return a; }, auto b = decltype(b){});
f<float*>(); // OK
template<class T> pair<auto...> (*vfp)(auto...) = [](T t1, T* t2)
{ return make_pair(t1, t2); };
Thanks!
Faisal Vali
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Bjarne Stroustrup
2015-03-04 16:17:22 UTC
Permalink
Post by Gabriel Dos Reis
Should we declare "auto f(auto) -> auto" an excess in sophism?
and those two "auto"s can denote different and unrelated types?
Post by Gabriel Dos Reis
-- Gaby
Post by Faisal Vali
In the hopes of soliciting constructive feedback, if anyone has the
time or the interest to play with a patched up Clang that implements
enhanced auto deduction & abbreviated template syntax from the
https://github.com/faisalv/clang/tree/enhanced-auto-c%2B%2B1z .
The last line of the README file tells you the subversion revision of
LLVM to use.
-- https://github.com/faisalv/clang/blob/enhanced-auto-c%2B%2B1z/test/CXX/auto/cxx1z-auto-vars-generalized.cpp
-- https://github.com/faisalv/clang/blob/enhanced-auto-c%2B%2B1z/test/CXX/auto/cxx1z-abbreviated-templates.cpp
I would certainly appreciate the feedback!
pair<auto...> f() { return make_pair([] { }, [] { }); }
vector<auto> v = vector<int>();
void f(auto) <=> template<class T> void f(T);
a) The equivalence of templates when it comes to trailing return
types in function pointer parameters is based on the order of the
'auto' that signifies a placeholder, not just the appearance of an
template<class R, class P> void f( R(P) ); // #1
template<class P, class R> void f( R(P) ); // #2 (order of
templ-params flipped)
template<class R, class P> void f( auto (P)->R); // equivalent to
#1, not abbreviated.
void f(auto(auto)); // equivalent to #1
void f(auto (auto) -> auto); // equivalent to #2
// the trailing return type auto
// identifies a
template parameter
template<class R> void f(R(auto); // equivalent to #1
template<class P> void f(auto(P)); // equivalent to #2
b) variadic auto
Once an ellipsis is seen as part of the declarator, all contained
auto placeholders get transformed into parameter packs.
void f(auto (*...)(auto) -> std::tuple<auto, std::pair<auto, auto>...>);
Note there are 4 deducible template parameter packs above.
c) multi abbreviated template declarations
void f(auto), g(auto);
are allowed - the above declares two function templates.
d) template aliases desugar their types *after* each auto has been
identified as a placeholder (and so must be deduced)
template<class T> using Int = int;
Int<auto> i = 3; // Is an error, auto must be deducible.
void f(int (*)(int) = [](auto a) { return a; }, auto b = decltype(b){});
f<float*>(); // OK
template<class T> pair<auto...> (*vfp)(auto...) = [](T t1, T* t2)
{ return make_pair(t1, t2); };
Thanks!
Faisal Vali
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Faisal Vali
2015-03-04 16:40:57 UTC
Permalink
On Wed, Mar 4, 2015 at 10:17 AM, Bjarne Stroustrup
Post by Bjarne Stroustrup
Post by Gabriel Dos Reis
Should we declare "auto f(auto) -> auto" an excess in sophism?
and those two "auto"s can denote different and unrelated types?
yes - the first 'auto' is a trailing return type signifier, the second
'auto' is an abbreviated template signifier (adds a template parameter
to the function template's template parameter list) and is deduced
from the supplied argument, the third auto is the placeholder for
return type deduction and is deduced from a return statement within
the body of the function - it does not add a template parameter to
the function template's template parameter list - and is quite
different from the second auto in that way.
Post by Bjarne Stroustrup
Post by Gabriel Dos Reis
-- Gaby
Post by Faisal Vali
In the hopes of soliciting constructive feedback, if anyone has the
time or the interest to play with a patched up Clang that implements
enhanced auto deduction & abbreviated template syntax from the
https://github.com/faisalv/clang/tree/enhanced-auto-c%2B%2B1z .
The last line of the README file tells you the subversion revision of
LLVM to use.
--
https://github.com/faisalv/clang/blob/enhanced-auto-c%2B%2B1z/test/CXX/auto/cxx1z-auto-vars-generalized.cpp
--
https://github.com/faisalv/clang/blob/enhanced-auto-c%2B%2B1z/test/CXX/auto/cxx1z-abbreviated-templates.cpp
I would certainly appreciate the feedback!
pair<auto...> f() { return make_pair([] { }, [] { }); }
vector<auto> v = vector<int>();
void f(auto) <=> template<class T> void f(T);
a) The equivalence of templates when it comes to trailing return
types in function pointer parameters is based on the order of the
'auto' that signifies a placeholder, not just the appearance of an
template<class R, class P> void f( R(P) ); // #1
template<class P, class R> void f( R(P) ); // #2 (order of
templ-params flipped)
template<class R, class P> void f( auto (P)->R); // equivalent to
#1, not abbreviated.
void f(auto(auto)); // equivalent to #1
void f(auto (auto) -> auto); // equivalent to #2
// the trailing return type auto
// identifies a
template parameter
template<class R> void f(R(auto); // equivalent to #1
template<class P> void f(auto(P)); // equivalent to #2
b) variadic auto
Once an ellipsis is seen as part of the declarator, all contained
auto placeholders get transformed into parameter packs.
void f(auto (*...)(auto) -> std::tuple<auto, std::pair<auto, auto>...>);
Note there are 4 deducible template parameter packs above.
c) multi abbreviated template declarations
void f(auto), g(auto);
are allowed - the above declares two function templates.
d) template aliases desugar their types *after* each auto has been
identified as a placeholder (and so must be deduced)
template<class T> using Int = int;
Int<auto> i = 3; // Is an error, auto must be deducible.
void f(int (*)(int) = [](auto a) { return a; }, auto b =
decltype(b){});
f<float*>(); // OK
template<class T> pair<auto...> (*vfp)(auto...) = [](T t1, T* t2)
{ return make_pair(t1, t2); };
Thanks!
Faisal Vali
--
---
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
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-proposals/.
--
--- You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Gabriel Dos Reis
2015-03-04 16:55:52 UTC
Permalink
But the "late return type" signifier was there only because we could not get the natural and simpler syntax in C++11!

I am hoping we are not retaining complexity only because we can.

"auto" is the new "static".

-- Gaby
Post by Faisal Vali
On Wed, Mar 4, 2015 at 10:17 AM, Bjarne Stroustrup
Post by Bjarne Stroustrup
Post by Gabriel Dos Reis
Should we declare "auto f(auto) -> auto" an excess in sophism?
and those two "auto"s can denote different and unrelated types?
yes - the first 'auto' is a trailing return type signifier, the second
'auto' is an abbreviated template signifier (adds a template parameter
to the function template's template parameter list) and is deduced
from the supplied argument, the third auto is the placeholder for
return type deduction and is deduced from a return statement within
the body of the function - it does not add a template parameter to
the function template's template parameter list - and is quite
different from the second auto in that way.
Post by Bjarne Stroustrup
Post by Gabriel Dos Reis
-- Gaby
Post by Faisal Vali
In the hopes of soliciting constructive feedback, if anyone has the
time or the interest to play with a patched up Clang that implements
enhanced auto deduction & abbreviated template syntax from the
https://github.com/faisalv/clang/tree/enhanced-auto-c%2B%2B1z .
The last line of the README file tells you the subversion revision of
LLVM to use.
--
https://github.com/faisalv/clang/blob/enhanced-auto-c%2B%2B1z/test/CXX/auto/cxx1z-auto-vars-generalized.cpp
--
https://github.com/faisalv/clang/blob/enhanced-auto-c%2B%2B1z/test/CXX/auto/cxx1z-abbreviated-templates.cpp
I would certainly appreciate the feedback!
pair<auto...> f() { return make_pair([] { }, [] { }); }
vector<auto> v = vector<int>();
void f(auto) <=> template<class T> void f(T);
a) The equivalence of templates when it comes to trailing return
types in function pointer parameters is based on the order of the
'auto' that signifies a placeholder, not just the appearance of an
template<class R, class P> void f( R(P) ); // #1
template<class P, class R> void f( R(P) ); // #2 (order of
templ-params flipped)
template<class R, class P> void f( auto (P)->R); // equivalent to
#1, not abbreviated.
void f(auto(auto)); // equivalent to #1
void f(auto (auto) -> auto); // equivalent to #2
// the trailing return type auto
// identifies a
template parameter
template<class R> void f(R(auto); // equivalent to #1
template<class P> void f(auto(P)); // equivalent to #2
b) variadic auto
Once an ellipsis is seen as part of the declarator, all contained
auto placeholders get transformed into parameter packs.
void f(auto (*...)(auto) -> std::tuple<auto, std::pair<auto, auto>...>);
Note there are 4 deducible template parameter packs above.
c) multi abbreviated template declarations
void f(auto), g(auto);
are allowed - the above declares two function templates.
d) template aliases desugar their types *after* each auto has been
identified as a placeholder (and so must be deduced)
template<class T> using Int = int;
Int<auto> i = 3; // Is an error, auto must be deducible.
void f(int (*)(int) = [](auto a) { return a; }, auto b =
decltype(b){});
f<float*>(); // OK
template<class T> pair<auto...> (*vfp)(auto...) = [](T t1, T* t2)
{ return make_pair(t1, t2); };
Thanks!
Faisal Vali
--
---
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
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-proposals/.
--
--- You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Arthur O'Dwyer
2015-03-04 05:36:02 UTC
Permalink
Post by Faisal Vali
In the hopes of soliciting constructive feedback, if anyone has the
time or the interest to play with a patched up Clang that implements
enhanced auto deduction & abbreviated template syntax from the
https://github.com/faisalv/clang/tree/enhanced-auto-c%2B%2B1z .
That's *very very cool* — at least the "abbreviated template syntax" half!
;) Is it possible for you to separate out the "abbreviated template
syntax" feature from the "enhanced auto detection" feature, into two
separate patches that could be looked at and/or adopted individually?

Now that we have generic lambdas (in C++14), I'm looking forward to having
"generic functions" (i.e., abbreviated template syntax) sooner rather than
later.

// C++14: Create a lambda object with a template member operator()
auto f = [](auto x, auto y) { return x + y; };

// C++1z: Create a template function directly
auto f(auto x, auto y) { return x + y; }
Post by Faisal Vali
pair<auto...> f() { return make_pair([] { }, [] { }); }
vector<auto> v = vector<int>();
I don't see the use-case for this feature. Why would I write

vector<auto> v = vector<int>();

when it's less typing and less noise to just write

auto v = vector<int>();

? Also, as you noted in technicality (d), it's impossible to support
"enhanced deduction" for type aliases. I don't like the asymmetry this
creates between "class types" and "typedef types". Here are a collection
of "enhanced" cases where deduction fails (in some cases, MUST fail).

template<class T> using identity1 = T;
identity1<auto> id1 = 42;
template<class T> struct identity2 { using type = T; };
identity2<auto>::type id2 = 42;
template<class T> struct int3 { using type = int; };
int3<auto>::type id3 = 42;
template<class> using int4 = int;
int4<auto> id4 = 42;

I'm mostly concerned with the fact that you're making identity1<auto> fail,
while vector<auto> succeeds.

Here's a use-case I could maybe get behind:

vector<auto> vec = { 1, 2, 3 }; // creates a vector of int

except that (correct me if I'm wrong) your patch doesn't support that
use-case. And I'm not sure how it could.
Post by Faisal Vali
void f(auto) <=> template<class T> void f(T);
THIS is the very very awesome part. I am super excited about this feature
finally coming to a compiler near me!
Post by Faisal Vali
a) The equivalence of templates when it comes to trailing return
types in function pointer parameters is based on the order of the
'auto' that signifies a placeholder, not just the appearance of an
template<class R, class P> void f( R(P) ); // #1
template<class P, class R> void f( R(P) ); // #2 (order of
templ-params flipped)
template<class R, class P> void f( auto (P)->R); // equivalent to
#1, not abbreviated.
How many of these weirdnesses vanish if you get rid of "enhanced auto
deduction"?
Clang 3.7.0 doesn't currently allow trailing return types on C++14 generic
lambda parameters, which IMHO is a feature (in that allowing them leads to
the grotesqueries you mention) but I'm pretty sure from the Standard's POV
is a bug. (Contrariwise, I think GCC 5.0.0 is *too* permissive. But in
neither case am I sure exactly what's allowed by the Standard.)

http://melpon.org/wandbox/permlink/QMQXHNsBmwVJbxM0
int one(int (*f)(int)) { return f(42); } // C++03
int two(auto (*f)(int) -> int) { return f(42); } // C++11
int three(auto (*f)(int)) { return f(42); } // never
int four(auto (*f)(int) -> auto) { return f(42); } // never
int five(int (*f)(auto)) { return f(42); } // never
int six(int f(int)) { return f(42); } // C++03 (takes a function pointer)
int seven(int f(auto)) { return f(42); } // never


auto bone = [](int (*f)(int)) { return f(42); }; // C++11
auto btwo = [](auto (*f)(int) -> int) { return f(42); }; // never
auto bthree = [](auto (*f)(int)) { return f(42); }; // C++14
auto bfour = [](auto (*f)(int) -> auto) { return f(42); }; // never
auto bfive = [](int (*f)(auto)) { return f(42); }; // never
auto bsix = [](int f(int)) { return f(42); }; // C++11 (takes a function
pointer)
auto bseven = [](int f(auto)) { return f(42); }; // never
Post by Faisal Vali
void f(auto(auto)); // equivalent to #1
IMHO, this should be disallowed. It deduces a function type for the
parameter, and then "decays" that type to a function pointer, in the same
way that parameters of array type "decay" to pointers. This was inherited
from C, is super confusing, and in an age of generic lambda functors really
deserves to be put to bed.

auto f(auto ga(auto)) { return ga("hello world"); }
auto g(auto xa) { puts(xa); }
int main() { f(g); }

Today, even though it looks like ga and g have the same type, they don't! g
is a function *template*, and ga is a *pointer to a function of unspecified
type*.
The idiomatically correct signature for f IMHO would be

auto f(auto *ga) { return ga("hello world"); }


b) variadic auto
Post by Faisal Vali
Once an ellipsis is seen as part of the declarator, all contained
auto placeholders get transformed into parameter packs.
void f(auto (*...)(auto) -> std::tuple<auto, std::pair<auto, auto>...>);
Note there are 4 deducible template parameter packs above.
Do I understand correctly that the above is exactly equivalent to

template<class... A, class... B, class... C, class... D>
void f1(std::tuple<A, std::pair<B,C>...> (*...args)(D));

void f2(std::tuple<auto, std::pair<auto,auto>...> (*...args)(auto));

where f1 uses C++11 syntax and f2 uses only "abbreviated template" syntax?

c) multi abbreviated template declarations
Post by Faisal Vali
void f(auto), g(auto);
are allowed - the above declares two function templates.
That's not allowed for non-abbreviated templates, and again I don't see a
use-case for it. What's a case where I would want to chain together
function declarations like that? Again, that seems like cruft inherited
from C that could easily be dumped at least for new syntax.

You don't mention this as a pitfall, but looking at your test cases I
observed that

auto foo = 42; // foo is definitely an int
void bar(auto baz = 42); // baz is NOT an int; it's of some deduced
type.
// The initializer 42 is coerced to that type
if necessary.

Consider the following progression:

template<class X, class Y=int> auto one(X x, Y y=1) { return x+y; }; //
legal C++14
template<class X, class Y> auto two(X x, Y y=1) { return x+y; }; //
invalid, and rightly so
auto three = [](auto x, auto y=1) { return x+y; }; // invalid, but I claim
it has an obvious meaning that should be standardized
auto four(auto x, auto y=1) { return x+y; }; // invalid?? with your patch,
but I claim it has an obvious meaning
int main() { one(1); two(2); three(3); four(4); }

I know this has been a massive and scattered array of potshots, but I hope
you find some of it interesting and/or useful. :)

–Arthur
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Jonathan Wakely
2015-03-04 11:13:49 UTC
Permalink
Post by Arthur O'Dwyer
Post by Faisal Vali
void f(auto) <=> template<class T> void f(T);
THIS is the very very awesome part. I am super excited about this feature
finally coming to a compiler near me!
Like GCC 4.9, released a year ago? :-)

https://gcc.gnu.org/gcc-4.9/changes.html#cxx
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Faisal Vali
2015-03-04 12:45:02 UTC
Permalink
On Tue, Mar 3, 2015 at 11:36 PM, Arthur O'Dwyer
Post by Faisal Vali
In the hopes of soliciting constructive feedback, if anyone has the
time or the interest to play with a patched up Clang that implements
enhanced auto deduction & abbreviated template syntax from the
https://github.com/faisalv/clang/tree/enhanced-auto-c%2B%2B1z .
That's very very cool — at least the "abbreviated template syntax" half! ;)
Is it possible for you to separate out the "abbreviated template syntax"
feature from the "enhanced auto detection" feature, into two separate
patches that could be looked at and/or adopted individually?
Now that we have generic lambdas (in C++14), I'm looking forward to having
"generic functions" (i.e., abbreviated template syntax) sooner rather than
later.
// C++14: Create a lambda object with a template member operator()
auto f = [](auto x, auto y) { return x + y; };
// C++1z: Create a template function directly
auto f(auto x, auto y) { return x + y; }
Post by Faisal Vali
pair<auto...> f() { return make_pair([] { }, [] { }); }
vector<auto> v = vector<int>();
I don't see the use-case for this feature. Why would I write
vector<auto> v = vector<int>();
when it's less typing and less noise to just write
auto v = vector<int>();
I generally agree with the above statement - but there are some who
have argued that it can improve readability - and I see their point
too.
? Also, as you noted in technicality (d), it's impossible to support
"enhanced deduction" for type aliases. I don't like the asymmetry this
creates between "class types" and "typedef types". Here are a collection of
"enhanced" cases where deduction fails (in some cases, MUST fail).
template<class T> using identity1 = T;
identity1<auto> id1 = 42;
template<class T> struct identity2 { using type = T; };
identity2<auto>::type id2 = 42;
template<class T> struct int3 { using type = int; };
int3<auto>::type id3 = 42;
template<class> using int4 = int;
int4<auto> id4 = 42;
I'm mostly concerned with the fact that you're making identity1<auto> fail,
while vector<auto> succeeds.
Sorry, I was unclear - identity1<auto> id1 = 42 is the only one of
your examples that works. What does not work is: if you invent a
template parameter for each placeholder in your declaration - but
while doing template argument deduction thru a function call, if any
template parameters are left undeduced - that's an error (even if the
alias does not use the template parameter after desugarring).
Consider:
template<class T> void f(int4<T> id4);
f(42); // Error.
vector<auto> vec = { 1, 2, 3 }; // creates a vector of int
except that (correct me if I'm wrong) your patch doesn't support that
use-case. And I'm not sure how it could.
No - since template argument deduction for function calls does not support that.
Post by Faisal Vali
void f(auto) <=> template<class T> void f(T);
THIS is the very very awesome part. I am super excited about this feature
finally coming to a compiler near me!
Hah - our gcc friends have had this for ages :) - I've submitted a
patch for clang's review - but if history is any indication - the
review cycles (my latencies included) can take months.
Post by Faisal Vali
a) The equivalence of templates when it comes to trailing return
types in function pointer parameters is based on the order of the
'auto' that signifies a placeholder, not just the appearance of an
template<class R, class P> void f( R(P) ); // #1
template<class P, class R> void f( R(P) ); // #2 (order of
templ-params flipped)
template<class R, class P> void f( auto (P)->R); // equivalent to
#1, not abbreviated.
How many of these weirdnesses vanish if you get rid of "enhanced auto
deduction"?
None - this has nothing to do with initializer deduction - only
trailing return type syntax.
Clang 3.7.0 doesn't currently allow trailing return types on C++14 generic
lambda parameters, which IMHO is a feature (in that allowing them leads to
the grotesqueries you mention) but I'm pretty sure from the Standard's POV
is a bug. (Contrariwise, I think GCC 5.0.0 is *too* permissive. But in
neither case am I sure exactly what's allowed by the Standard.)
No one is sure (except for maybe 10 or so kingsmen* that round table
it ~twice a year) exactly what's allowed by the standard ;)
(*) gender neutrality invoked
http://melpon.org/wandbox/permlink/QMQXHNsBmwVJbxM0
int one(int (*f)(int)) { return f(42); } // C++03
int two(auto (*f)(int) -> int) { return f(42); } // C++11
int three(auto (*f)(int)) { return f(42); } // never
int four(auto (*f)(int) -> auto) { return f(42); } // never
int five(int (*f)(auto)) { return f(42); } // never
int six(int f(int)) { return f(42); } // C++03 (takes a function pointer)
int seven(int f(auto)) { return f(42); } // never
auto bone = [](int (*f)(int)) { return f(42); }; // C++11
auto btwo = [](auto (*f)(int) -> int) { return f(42); }; // never
auto bthree = [](auto (*f)(int)) { return f(42); }; // C++14
auto bfour = [](auto (*f)(int) -> auto) { return f(42); }; // never
auto bfive = [](int (*f)(auto)) { return f(42); }; // never
auto bsix = [](int f(int)) { return f(42); }; // C++11 (takes a function
pointer)
auto bseven = [](int f(auto)) { return f(42); }; // never
Post by Faisal Vali
void f(auto(auto)); // equivalent to #1
IMHO, this should be disallowed. It deduces a function type for the
parameter, and then "decays" that type to a function pointer, in the same
way that parameters of array type "decay" to pointers. This was inherited
from C, is super confusing, and in an age of generic lambda functors really
deserves to be put to bed.
I hear you - but it is easier to write test cases without the extra
syntax to denote a ptr or ref.
auto f(auto ga(auto)) { return ga("hello world"); }
auto g(auto xa) { puts(xa); }
int main() { f(g); }
Today, even though it looks like ga and g have the same type, they don't! g
is a function template, and ga is a pointer to a function of unspecified
type.
The idiomatically correct signature for f IMHO would be
auto f(auto *ga) { return ga("hello world"); }
Post by Faisal Vali
b) variadic auto
Once an ellipsis is seen as part of the declarator, all contained
auto placeholders get transformed into parameter packs.
void f(auto (*...)(auto) -> std::tuple<auto, std::pair<auto, auto>...>);
Note there are 4 deducible template parameter packs above.
Do I understand correctly that the above is exactly equivalent to
template<class... A, class... B, class... C, class... D>
void f1(std::tuple<A, std::pair<B,C>...> (*...args)(D));
void f2(std::tuple<auto, std::pair<auto,auto>...> (*...args)(auto));
where f1 uses C++11 syntax and f2 uses only "abbreviated template" syntax?
Yes.
Post by Faisal Vali
c) multi abbreviated template declarations
void f(auto), g(auto);
are allowed - the above declares two function templates.
That's not allowed for non-abbreviated templates, and again I don't see a
use-case for it. What's a case where I would want to chain together function
declarations like that? Again, that seems like cruft inherited from C that
could easily be dumped at least for new syntax.
I don't think I care much either way - but I don't think this
forbidden by the TS.
You don't mention this as a pitfall, but looking at your test cases I
observed that
auto foo = 42; // foo is definitely an int
void bar(auto baz = 42); // baz is NOT an int; it's of some deduced
type.
// The initializer 42 is coerced to that type
if necessary.
Yes - I can see the potential for confusion - but perhaps if you
mentally replace an 'auto' in a function declaration with a template
type parameter, and in an initializer deduction with a function call
with the initializer, perhaps the confusion can be minimized - but I
agree, it is unfortunate that such asymmetry exists.
template<class X, class Y=int> auto one(X x, Y y=1) { return x+y; }; //
legal C++14
template<class X, class Y> auto two(X x, Y y=1) { return x+y; }; //
invalid, and rightly so
auto three = [](auto x, auto y=1) { return x+y; }; // invalid, but I claim
it has an obvious meaning that should be standardized
auto four(auto x, auto y=1) { return x+y; }; // invalid?? with your patch,
but I claim it has an obvious meaning
int main() { one(1); two(2); three(3); four(4); }
I know this has been a massive and scattered array of potshots, but I hope
you find some of it interesting and/or useful. :)
–Arthur
I certainly did - Thanks!
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Ville Voutilainen
2015-03-04 12:49:02 UTC
Permalink
Post by Faisal Vali
Post by Arthur O'Dwyer
I don't see the use-case for this feature. Why would I write
vector<auto> v = vector<int>();
when it's less typing and less noise to just write
auto v = vector<int>();
I generally agree with the above statement - but there are some who
have argued that it can improve readability - and I see their point
too.
That's a bad example for it. A better one is
vector<auto> v = some_function();
where you don't care about the exact return type of some_function,
but you do want to ensure it's a vector. Such ensuring is indeed completely
unnecessary for the example above where the type created is visible
in a crystal clear fashion.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Bjarne Stroustrup
2015-03-04 16:14:44 UTC
Permalink
Post by Ville Voutilainen
Post by Faisal Vali
Post by Arthur O'Dwyer
I don't see the use-case for this feature. Why would I write
vector<auto> v = vector<int>();
when it's less typing and less noise to just write
auto v = vector<int>();
I generally agree with the above statement - but there are some who
have argued that it can improve readability - and I see their point
too.
That's a bad example for it. A better one is
vector<auto> v = some_function();
where you don't care about the exact return type of some_function,
but you do want to ensure it's a vector. Such ensuring is indeed completely
unnecessary for the example above where the type created is visible
in a crystal clear fashion.
and then, with suitable concepts and a much-asked-for extension of
concepts to allow placement of concepts roughly wherever "auto" can be
placed:

Container v = some_function();

and

vector<Some_string_type> v = some_function();
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Tony Van Eerd
2015-03-04 17:15:06 UTC
Permalink
Post by Bjarne Stroustrup
and then, with suitable concepts and a much-asked-for extension of
concepts to allow placement of concepts roughly wherever "auto" can be
Container v = some_function();
Yes please.

To me, auto has the same problems as templates without concepts.
Tony
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Bjarne Stroustrup
2015-03-04 17:55:19 UTC
Permalink
Post by Tony Van Eerd
Post by Bjarne Stroustrup
and then, with suitable concepts and a much-asked-for extension of
concepts to allow placement of concepts roughly wherever "auto" can be
Container v = some_function();
Yes please.
To me, auto has the same problems as templates without concepts.
Tony
Exactly
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Klaim - Joël Lamotte
2015-03-04 12:50:29 UTC
Permalink
Post by Faisal Vali
Post by Arthur O'Dwyer
I don't see the use-case for this feature. Why would I write
vector<auto> v = vector<int>();
when it's less typing and less noise to just write
auto v = vector<int>();
I generally agree with the above statement - but there are some who
have argued that it can improve readability - and I see their point
too.
Another argument would be that if you have

auto v = generateData();

It is less constrained than

vector<auto> v = generateData();

which add an interesting constraint that generateData() must return a
vector, not just something that
have the same interface.
It looks like improved granularity on constraints specifications.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Faisal Vali
2015-03-04 17:28:46 UTC
Permalink
Post by Faisal Vali
On Tue, Mar 3, 2015 at 11:36 PM, Arthur O'Dwyer
<snip>
Post by Faisal Vali
Post by Arthur O'Dwyer
Post by Faisal Vali
b) variadic auto
Once an ellipsis is seen as part of the declarator, all contained
auto placeholders get transformed into parameter packs.
void f(auto (*...)(auto) -> std::tuple<auto, std::pair<auto, auto>...>);
Note there are 4 deducible template parameter packs above.
Do I understand correctly that the above is exactly equivalent to
template<class... A, class... B, class... C, class... D>
void f1(std::tuple<A, std::pair<B,C>...> (*...args)(D));
void f2(std::tuple<auto, std::pair<auto,auto>...> (*...args)(auto));
where f1 uses C++11 syntax and f2 uses only "abbreviated template" syntax?
Yes.
Hmm - just a minor technicality, but actually, they are not all
redeclarations of the same template, the two that you wrote are
equivalent to each other, but the first one is equivalent to the
following (note the order of the template parameters)
template<class ... A, class ... B, class... C, class...D>
void f(tuple<B, pair<C,D>...)(*...)(A));

in case anyone cares ...
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Matthew Fioravante
2015-03-04 17:14:12 UTC
Permalink
Post by Arthur O'Dwyer
I don't see the use-case for this feature. Why would I write
vector<auto> v = vector<int>();
when it's less typing and less noise to just write
auto v = vector<int>();
The use case for this:

vector<int> v;

array_view<auto> av = v; //deduces to array_view<int>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
'Geoffrey Romer' via ISO C++ Standard - Discussion
2015-03-04 17:59:44 UTC
Permalink
Post by Arthur O'Dwyer
Post by Faisal Vali
In the hopes of soliciting constructive feedback, if anyone has the
time or the interest to play with a patched up Clang that implements
enhanced auto deduction & abbreviated template syntax from the
https://github.com/faisalv/clang/tree/enhanced-auto-c%2B%2B1z .
That's *very very cool* — at least the "abbreviated template syntax"
half! ;)
Interesting; my reaction is precisely the opposite- I find enhanced auto
deduction very appealing (for reasons that others on this thread have
elaborated), but am actively uninterested in the abbreviated template
syntax. It seems to me to offer only a modest improvement in brevity, and
pays for it with a very substantial reduction in readability. That
compromise may be appropriate for lambdas, because brevity is particularly
important inside a single expression, but it seems far less justifiable in
the case of ordinary functions. Functions are not under the kinds of space
constraints that lambdas are, and function signatures (unlike lambda
signatures) often act as abstraction boundaries, so it's particularly
important for them to convey useful information to the reader.
Post by Arthur O'Dwyer
Is it possible for you to separate out the "abbreviated template syntax"
feature from the "enhanced auto detection" feature, into two separate
patches that could be looked at and/or adopted individually?
Now that we have generic lambdas (in C++14), I'm looking forward to having
"generic functions" (i.e., abbreviated template syntax) sooner rather than
later.
// C++14: Create a lambda object with a template member operator()
auto f = [](auto x, auto y) { return x + y; };
// C++1z: Create a template function directly
auto f(auto x, auto y) { return x + y; }
Post by Faisal Vali
pair<auto...> f() { return make_pair([] { }, [] { }); }
vector<auto> v = vector<int>();
I don't see the use-case for this feature. Why would I write
vector<auto> v = vector<int>();
when it's less typing and less noise to just write
auto v = vector<int>();
? Also, as you noted in technicality (d), it's impossible to support
"enhanced deduction" for type aliases. I don't like the asymmetry this
creates between "class types" and "typedef types". Here are a collection
of "enhanced" cases where deduction fails (in some cases, MUST fail).
template<class T> using identity1 = T;
identity1<auto> id1 = 42;
template<class T> struct identity2 { using type = T; };
identity2<auto>::type id2 = 42;
template<class T> struct int3 { using type = int; };
int3<auto>::type id3 = 42;
template<class> using int4 = int;
int4<auto> id4 = 42;
I'm mostly concerned with the fact that you're making identity1<auto>
fail, while vector<auto> succeeds.
vector<auto> vec = { 1, 2, 3 }; // creates a vector of int
except that (correct me if I'm wrong) your patch doesn't support that
use-case. And I'm not sure how it could.
Post by Faisal Vali
void f(auto) <=> template<class T> void f(T);
THIS is the very very awesome part. I am super excited about this feature
finally coming to a compiler near me!
Post by Faisal Vali
a) The equivalence of templates when it comes to trailing return
types in function pointer parameters is based on the order of the
'auto' that signifies a placeholder, not just the appearance of an
template<class R, class P> void f( R(P) ); // #1
template<class P, class R> void f( R(P) ); // #2 (order of
templ-params flipped)
template<class R, class P> void f( auto (P)->R); // equivalent to
#1, not abbreviated.
How many of these weirdnesses vanish if you get rid of "enhanced auto
deduction"?
Clang 3.7.0 doesn't currently allow trailing return types on C++14 generic
lambda parameters, which IMHO is a feature (in that allowing them leads to
the grotesqueries you mention) but I'm pretty sure from the Standard's POV
is a bug. (Contrariwise, I think GCC 5.0.0 is *too* permissive. But in
neither case am I sure exactly what's allowed by the Standard.)
http://melpon.org/wandbox/permlink/QMQXHNsBmwVJbxM0
int one(int (*f)(int)) { return f(42); } // C++03
int two(auto (*f)(int) -> int) { return f(42); } // C++11
int three(auto (*f)(int)) { return f(42); } // never
int four(auto (*f)(int) -> auto) { return f(42); } // never
int five(int (*f)(auto)) { return f(42); } // never
int six(int f(int)) { return f(42); } // C++03 (takes a function pointer)
int seven(int f(auto)) { return f(42); } // never
auto bone = [](int (*f)(int)) { return f(42); }; // C++11
auto btwo = [](auto (*f)(int) -> int) { return f(42); }; // never
auto bthree = [](auto (*f)(int)) { return f(42); }; // C++14
auto bfour = [](auto (*f)(int) -> auto) { return f(42); }; // never
auto bfive = [](int (*f)(auto)) { return f(42); }; // never
auto bsix = [](int f(int)) { return f(42); }; // C++11 (takes a function
pointer)
auto bseven = [](int f(auto)) { return f(42); }; // never
Post by Faisal Vali
void f(auto(auto)); // equivalent to #1
IMHO, this should be disallowed. It deduces a function type for the
parameter, and then "decays" that type to a function pointer, in the same
way that parameters of array type "decay" to pointers. This was inherited
from C, is super confusing, and in an age of generic lambda functors really
deserves to be put to bed.
auto f(auto ga(auto)) { return ga("hello world"); }
auto g(auto xa) { puts(xa); }
int main() { f(g); }
Today, even though it looks like ga and g have the same type, they don't!
g is a function *template*, and ga is a *pointer to a function of
unspecified type*.
The idiomatically correct signature for f IMHO would be
auto f(auto *ga) { return ga("hello world"); }
b) variadic auto
Post by Faisal Vali
Once an ellipsis is seen as part of the declarator, all contained
auto placeholders get transformed into parameter packs.
void f(auto (*...)(auto) -> std::tuple<auto, std::pair<auto, auto>...>);
Note there are 4 deducible template parameter packs above.
Do I understand correctly that the above is exactly equivalent to
template<class... A, class... B, class... C, class... D>
void f1(std::tuple<A, std::pair<B,C>...> (*...args)(D));
void f2(std::tuple<auto, std::pair<auto,auto>...> (*...args)(auto));
where f1 uses C++11 syntax and f2 uses only "abbreviated template" syntax?
c) multi abbreviated template declarations
Post by Faisal Vali
void f(auto), g(auto);
are allowed - the above declares two function templates.
That's not allowed for non-abbreviated templates, and again I don't see a
use-case for it. What's a case where I would want to chain together
function declarations like that? Again, that seems like cruft inherited
from C that could easily be dumped at least for new syntax.
You don't mention this as a pitfall, but looking at your test cases I
observed that
auto foo = 42; // foo is definitely an int
void bar(auto baz = 42); // baz is NOT an int; it's of some deduced
type.
// The initializer 42 is coerced to that
type if necessary.
template<class X, class Y=int> auto one(X x, Y y=1) { return x+y; }; //
legal C++14
template<class X, class Y> auto two(X x, Y y=1) { return x+y; }; //
invalid, and rightly so
auto three = [](auto x, auto y=1) { return x+y; }; // invalid, but I
claim it has an obvious meaning that should be standardized
auto four(auto x, auto y=1) { return x+y; }; // invalid?? with your
patch, but I claim it has an obvious meaning
int main() { one(1); two(2); three(3); four(4); }
I know this has been a massive and scattered array of potshots, but I hope
you find some of it interesting and/or useful. :)
–Arthur
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Jonathan Wakely
2015-03-05 11:23:44 UTC
Permalink
Post by 'Geoffrey Romer' via ISO C++ Standard - Discussion
Interesting; my reaction is precisely the opposite- I find enhanced auto
deduction very appealing (for reasons that others on this thread have
elaborated), but am actively uninterested in the abbreviated template
syntax. It seems to me to offer only a modest improvement in brevity, and
pays for it with a very substantial reduction in readability. That
compromise may be appropriate for lambdas, because brevity is particularly
important inside a single expression, but it seems far less justifiable in
the case of ordinary functions. Functions are not under the kinds of space
constraints that lambdas are, and function signatures (unlike lambda
signatures) often act as abstraction boundaries, so it's particularly
important for them to convey useful information to the reader.
This conveys useful information:

template<typename ForwardIterator>
ForwardIterator next(ForwardIterator);

but that's still true if it's rewritten like this:

ForwardIterator next(ForwardIterator);

This doesn't convey any useful information:

template<typename T>
void frob(T);

so in terms of describing the interface it's no different when written
like this:

void frob(auto);
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
'Geoffrey Romer' via ISO C++ Standard - Discussion
2015-03-05 17:11:58 UTC
Permalink
Post by 'Geoffrey Romer' via ISO C++ Standard - Discussion
Post by 'Geoffrey Romer' via ISO C++ Standard - Discussion
Interesting; my reaction is precisely the opposite- I find enhanced auto
deduction very appealing (for reasons that others on this thread have
elaborated), but am actively uninterested in the abbreviated template
syntax. It seems to me to offer only a modest improvement in brevity, and
pays for it with a very substantial reduction in readability. That
compromise may be appropriate for lambdas, because brevity is
particularly
Post by 'Geoffrey Romer' via ISO C++ Standard - Discussion
important inside a single expression, but it seems far less justifiable
in
Post by 'Geoffrey Romer' via ISO C++ Standard - Discussion
the case of ordinary functions. Functions are not under the kinds of
space
Post by 'Geoffrey Romer' via ISO C++ Standard - Discussion
constraints that lambdas are, and function signatures (unlike lambda
signatures) often act as abstraction boundaries, so it's particularly
important for them to convey useful information to the reader.
template<typename ForwardIterator>
ForwardIterator next(ForwardIterator);
ForwardIterator next(ForwardIterator);
That's not what I'm objecting to; I'm objecting to "auto" specifically. But
since you mention it, this version definitely conveys less information than
the previous one: it obscures the critical fact that 'next' is a function
template.
Post by 'Geoffrey Romer' via ISO C++ Standard - Discussion
template<typename T>
void frob(T);
I don't agree; it tells me that frob is a generic operation that works with
roughly any type T.
Post by 'Geoffrey Romer' via ISO C++ Standard - Discussion
so in terms of describing the interface it's no different when written
void frob(auto);
This is different because now I don't know anything about the requirements
or semantics of the parameter type. Even if a conceptified version of this
syntax is available, "auto" doesn't necessarily tell me that the operation
is generic; it may just mean that there's no named concept that captures
the meaning of the parameter.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Nevin Liber
2015-03-05 17:25:18 UTC
Permalink
On 5 March 2015 at 11:11, 'Geoffrey Romer' via ISO C++ Standard - Future
Post by 'Geoffrey Romer' via ISO C++ Standard - Discussion
Post by Jonathan Wakely
template<typename T>
void frob(T);
I don't agree; it tells me that frob is a generic operation that works
with roughly any type T.
But what does that mean? Sure, I can copy/move it (since it was passed by
value), but any other constraints will be dictated by the body of frob.
Post by 'Geoffrey Romer' via ISO C++ Standard - Discussion
Post by Jonathan Wakely
so in terms of describing the interface it's no different when written
void frob(auto);
This is different because now I don't know anything about the requirements
or semantics of the parameter type.
I'm just not seeing how that is any different (other than the incredibly
minor of having to call decltype on its parameter to get its type).

Do you have an example function body that works with frob(T) but doesn't
work with frob(auto) (or vice versa) for a specific concrete type? I'm
really trying to understand the difference you see between these two forms.
--
Nevin ":-)" Liber <mailto:***@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
'Geoffrey Romer' via ISO C++ Standard - Discussion
2015-03-05 18:10:44 UTC
Permalink
Post by Nevin Liber
On 5 March 2015 at 11:11, 'Geoffrey Romer' via ISO C++ Standard - Future
Post by 'Geoffrey Romer' via ISO C++ Standard - Discussion
Post by Jonathan Wakely
template<typename T>
void frob(T);
I don't agree; it tells me that frob is a generic operation that works
with roughly any type T.
But what does that mean? Sure, I can copy/move it (since it was passed by
value), but any other constraints will be dictated by the body of frob.
My point is that the use of a generic, meaningless parameter name like "T"
tacitly documents the fact that frob isn't going to dictate many additional
constraints, beyond perhaps highly generic ones like being able to compare
for equality.
Post by Nevin Liber
Post by 'Geoffrey Romer' via ISO C++ Standard - Discussion
Post by Jonathan Wakely
so in terms of describing the interface it's no different when written
void frob(auto);
This is different because now I don't know anything about the
requirements or semantics of the parameter type.
I'm just not seeing how that is any different (other than the incredibly
minor of having to call decltype on its parameter to get its type).
Do you have an example function body that works with frob(T) but doesn't
work with frob(auto) (or vice versa) for a specific concrete type? I'm
really trying to understand the difference you see between these two forms.
I'm not aware of any code that will work with one form but not the other.
My point is simply that "auto" conveys less information to me as a human
reader than a named template parameter would.
Post by Nevin Liber
--
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Ville Voutilainen
2015-03-05 19:09:55 UTC
Permalink
Dropping Core, this is not a Core discussion.

On 5 March 2015 at 20:10, 'Geoffrey Romer' via ISO C++ Standard -
Post by 'Geoffrey Romer' via ISO C++ Standard - Discussion
My point is that the use of a generic, meaningless parameter name like "T"
tacitly documents the fact that frob isn't going to dictate many additional
constraints, beyond perhaps highly generic ones like being able to compare
for equality.
void frob(auto); seemingly conveys the same information, once you get
used to it.
It also happens to be a nicely terse way to not write the
template-header boilerplate
for cases where you don't use that boilerplate for anything.
Post by 'Geoffrey Romer' via ISO C++ Standard - Discussion
Post by Nevin Liber
Do you have an example function body that works with frob(T) but doesn't
work with frob(auto) (or vice versa) for a specific concrete type? I'm
really trying to understand the difference you see between these two forms.
I'm not aware of any code that will work with one form but not the other. My
point is simply that "auto" conveys less information to me as a human reader
than a named template parameter would.
In
template <class T> void frob(T t)
{
// I can use T here for various purposes
}
and in
void frob(auto t)
{
// if I want to use 'T' here, I need to do a decltype(t) to get at it
}
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Matthew Fioravante
2015-03-05 23:43:15 UTC
Permalink
Post by Ville Voutilainen
void frob(auto t)
{
// if I want to use 'T' here, I need to do a decltype(t) to get at it
}
You may need remove pointer, ref, and/or cv qualifiers if you use auto*,
auto&& (perfect forwarding), const auto&, etc.. using type_traits. If the
signature changes, you'll have to remember to fix the traits you used.

If your implementation needs to express type T, it might be better to use
the old template syntax.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Ville Voutilainen
2015-03-05 23:52:39 UTC
Permalink
Post by Matthew Fioravante
Post by Ville Voutilainen
void frob(auto t)
{
// if I want to use 'T' here, I need to do a decltype(t) to get at it
}
You may need remove pointer, ref, and/or cv qualifiers if you use auto*,
auto&& (perfect forwarding), const auto&, etc.. using type_traits. If the
signature changes, you'll have to remember to fix the traits you used.
Yes. Not that the "signature changes" is all that much different from an
old-skool template.
Post by Matthew Fioravante
If your implementation needs to express type T, it might be better to use
the old template syntax.
Perhaps so. That may be a fairly big "if".
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Scott Prager
2015-03-06 01:22:10 UTC
Permalink
I can see where a lot of discomfort might come, here...

*(1) *Just plain auto seems imprecise and it makes template functions look
like
non-template functions.

*(2) *Named template parameters seem to provide comparatively more
information.

For *(1)*, this seems like a special case. When you consider inlining,
changing
functions that take reference parameters of basic types to pass by value,
and
other such optimizations our compilers perform, functions have never really
been the concrete entities we like to think of them as. I don't see a need
to
distinguish between template and non-template functions from a user
point-of-view, except when using *extern "C"*.

*(2)*: As mentioned, one can always fall back on normal template syntax, but
also, I don't know about anyone else, but I tend to name my types verbosely,
and my variables tersely. So I'll write...

template<class Sequence, class UnaryFunction>
void for_each(Sequence& seq, UnaryFunction f) { for(auto&& x : seq) f(x); }


...but with auto as the parameter type, I would reverse this trend:

void for_each(auto& sequence, auto unary_op) { for(auto&& x : sequence)
unary_op(x); }

...and I think that reads better.

Another reason I think we should embrace this: It brings template code
within
reach of absolute beginners, both to C++ and programming in general. Trying
to
teach an initiate what this means...

template<typename Function, typename Value>
auto f(Function fn, Value v) { return fn(v); }

requires teaching the meaning on "*typename*" (because the user may not have
needed typedefs or type aliases at this point), *template<...>*, how "
*Function*"
and "*Value*" do not denote real types, etc., etc.. But explaining this...

auto f(auto fn, auto val) { return fn(val); }

...well, they probably already are familiar with *auto*, using *auto* as a
parameter is intuitive, and those familiar with dynamic languages will feel
right at home, while benefiting from static typing.
Post by Ville Voutilainen
Post by Matthew Fioravante
Post by Ville Voutilainen
void frob(auto t)
{
// if I want to use 'T' here, I need to do a decltype(t) to get at
it
Post by Matthew Fioravante
Post by Ville Voutilainen
}
You may need remove pointer, ref, and/or cv qualifiers if you use auto*,
auto&& (perfect forwarding), const auto&, etc.. using type_traits. If
the
Post by Matthew Fioravante
signature changes, you'll have to remember to fix the traits you used.
Yes. Not that the "signature changes" is all that much different from an
old-skool template.
Post by Matthew Fioravante
If your implementation needs to express type T, it might be better to
use
Post by Matthew Fioravante
the old template syntax.
Perhaps so. That may be a fairly big "if".
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Tom Honermann
2015-03-05 20:28:09 UTC
Permalink
On 03/05/2015 01:10 PM, 'Geoffrey Romer' via ISO C++ Standard - Future
Post by 'Geoffrey Romer' via ISO C++ Standard - Discussion
I'm not aware of any code that will work with one form but not the
other. My point is simply that "auto" conveys less information to me as
a human reader than a named template parameter would.
I've felt concerns about this as well, specifically with respect to
behavioral differences observable in template functions vs non-template
functions.

We all know that there is one object with static storage duration
defined by this function:
void f(int i) {
static int invoke_count;
++invoke_count;
}

And we all know that there are potentially many objects with static
storage duration defined by this template function, one for each
instantiation:
template<typename T>
void f(int i) {
static int invoke_count;
++invoke_count;
}

But, it is less apparent how many objects with static storage duration
are defined by this function:
void f(auto t) {
static int invoke_count;
++invoke_count;
}

I don't know that this is a significant concern. But it is enough to
give me pause. I've personally never minded the template boilerplate,
but I guess I'm weird that way.

Tom.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
'Geoffrey Romer' via ISO C++ Standard - Discussion
2015-03-05 22:37:42 UTC
Permalink
Post by Tom Honermann
On 03/05/2015 01:10 PM, 'Geoffrey Romer' via ISO C++ Standard - Future
Post by 'Geoffrey Romer' via ISO C++ Standard - Discussion
I'm not aware of any code that will work with one form but not the
other. My point is simply that "auto" conveys less information to me as
a human reader than a named template parameter would.
I've felt concerns about this as well, specifically with respect to
behavioral differences observable in template functions vs non-template
functions.
We all know that there is one object with static storage duration defined
void f(int i) {
static int invoke_count;
++invoke_count;
}
And we all know that there are potentially many objects with static
storage duration defined by this template function, one for each
template<typename T>
void f(int i) {
static int invoke_count;
++invoke_count;
}
But, it is less apparent how many objects with static storage duration are
void f(auto t) {
static int invoke_count;
++invoke_count;
}
I don't know that this is a significant concern. But it is enough to give
me pause.
Another one: which of these definitions can safely be in a header file?
Post by Tom Honermann
I've personally never minded the template boilerplate, but I guess I'm
weird that way.
Me neither, and in fact I don't see the template header as "boilerplate" at
all. The only template boilerplate I mind is having to spell out

template <typename T, typename U, typename V>
MyClassName<T,U,V>::

over and over for every method I define outside the class body, but I don't
think abbreviated template syntax helps with that.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Thiago Macieira
2015-03-05 22:41:02 UTC
Permalink
Post by Tom Honermann
I don't know that this is a significant concern. But it is enough to
give me pause. I've personally never minded the template boilerplate,
but I guess I'm weird that way.
I'm with Tom here that the lack of "template" anywhere could lead people to
forget that the function is actually a template. I don't see this as a problem
for "auto", but it might be for concepts:

void f(Container t) {
static int invoke_count;
++invoke_count;
}

Is that a template or not? I need to look up the definition of Container to
figure out whether it's a concept or a regular class.

I wouldn't mind if we required the "template" keyword to appear in the
declaration of functions using concepts.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Andrew Sutton
2015-03-06 01:50:00 UTC
Permalink
Post by 'Geoffrey Romer' via ISO C++ Standard - Discussion
Post by Jonathan Wakely
template<typename ForwardIterator>
ForwardIterator next(ForwardIterator);
ForwardIterator next(ForwardIterator);
That's not what I'm objecting to; I'm objecting to "auto" specifically. But
since you mention it, this version definitely conveys less information than
the previous one: it obscures the critical fact that 'next' is a function
template.
Out of curiosity, why is next's template-ness a critical fact?

I've been writing a fair amount of C lately (and sadly). Many of the
functions I use turn out to be macros. I don't consider that to be a
critical fact. And when I'm writing C++, I generally don't care that
something I call is a template, only that there's an overload that
matches the arguments I call it with.

I've heard this argument before. I've yet to hear a good answer.

Andrew
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Nevin Liber
2015-03-06 02:09:22 UTC
Permalink
Post by Andrew Sutton
Out of curiosity, why is next's template-ness a critical fact?
I've been writing a fair amount of C lately (and sadly). Many of the
functions I use turn out to be macros. I don't consider that to be a
critical fact. And when I'm writing C++, I generally don't care that
something I call is a template, only that there's an overload that
matches the arguments I call it with.
I've heard this argument before. I've yet to hear a good answer.
The two (what I consider to be very minor) concerns I have:

1. Does the definition belong in a header for correctness?

2. Unintended code bloat, since every set of types produces a new
instantiation.

With the template syntax, you have a very visual way to point that out.
Both auto and concepts are not visually different than a concrete type.
(Well your IDE may be able to address this, but syntactically it isn't
visually different).
--
Nevin ":-)" Liber <mailto:***@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Andrew Sutton
2015-03-06 02:27:37 UTC
Permalink
Post by Nevin Liber
1. Does the definition belong in a header for correctness?
If it declares a function template, then almost certainly.

But as a user who's calling the function, does that matter? The
original comment focused on the information present in the
declaration. From that perspective, I think it matters little how the
function is declared (unless you try to take it's address).
Post by Nevin Liber
2. Unintended code bloat, since every set of types produces a new
instantiation.
With the template syntax, you have a very visual way to point that out.
Both auto and concepts are not visually different than a concrete type.
(Well your IDE may be able to address this, but syntactically it isn't
visually different).
That's a reasonable concern, but as you say, very minor. I don't think
I've ever chosen to use a different function because it wasn't a
template, but I can envision reasons for doing so :)

Andrew
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Thiago Macieira
2015-03-06 03:09:41 UTC
Permalink
Post by Andrew Sutton
Post by Nevin Liber
1. Does the definition belong in a header for correctness?
If it declares a function template, then almost certainly.
But as a user who's calling the function, does that matter? The
original comment focused on the information present in the
declaration. From that perspective, I think it matters little how the
function is declared (unless you try to take it's address).
That's exactly the point.

When you're just using a token, you may not care too much if it is a macro, a
regular function or a template function. You just want it to do the right job.

But if you look up its definition, it should be clear what it is. The argument
is that with a concept type, the fact that it's a template is hidden unless
you look up every single one of the types in the function's declaration.
Finding out whether it's a template function or a macro may important if you
Post by Andrew Sutton
Post by Nevin Liber
2. Unintended code bloat, since every set of types produces a new
instantiation.
With the template syntax, you have a very visual way to point that out.
Both auto and concepts are not visually different than a concrete type.
(Well your IDE may be able to address this, but syntactically it isn't
visually different).
That's a reasonable concern, but as you say, very minor. I don't think
I've ever chosen to use a different function because it wasn't a
template, but I can envision reasons for doing so :)
I don't think it would be a factor in whether you used it or not. But you may
want to make a note of that for future refactoring of the code, which requires
that you realise that you're doing it.

That said, there are better tools for noticing where the code bloat comes from
than making notes when writing code. We tend to think that the task we're
working on is the single most important thing to have ever happened, when in
the grand scheme of things it might be insignificant.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
John Spicer
2015-03-06 14:48:34 UTC
Permalink
Post by Andrew Sutton
Post by 'Geoffrey Romer' via ISO C++ Standard - Discussion
Post by Jonathan Wakely
template<typename ForwardIterator>
ForwardIterator next(ForwardIterator);
ForwardIterator next(ForwardIterator);
That's not what I'm objecting to; I'm objecting to "auto" specifically. But
since you mention it, this version definitely conveys less information than
the previous one: it obscures the critical fact that 'next' is a function
template.
Out of curiosity, why is next's template-ness a critical fact?
I've been writing a fair amount of C lately (and sadly). Many of the
functions I use turn out to be macros. I don't consider that to be a
critical fact. And when I'm writing C++, I generally don't care that
something I call is a template, only that there's an overload that
matches the arguments I call it with.
I've heard this argument before. I've yet to hear a good answer.
I don't think it is very important to the caller, but where next is defined it is important to those maintaining the code.

If ForwardIterator is a constrained-type-specifier, then next is a template, but if ForwardIterator is a type, it is not a template.

At least with "auto" you can figure out from the presence of "auto" that the function is a template.

I agree that the TS is a good chance to get experience and see what people like and don't like, provided that people don't use compatibility with what was specified in the TS for not changing a feature.

One possibility if we wanted some more syntax would be to require a template-introduction (14.2 in the Concepts TS) when a constrained-type-specifier is used, so next would be:

ForwardIterator{T} T next(T);

which, in this case, is shorter than the form without the template introduction.

John.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Zhihao Yuan
2015-03-05 18:57:57 UTC
Permalink
On Wed, Mar 4, 2015 at 12:59 PM, 'Geoffrey Romer' via ISO C++ Standard
Post by 'Geoffrey Romer' via ISO C++ Standard - Discussion
I find enhanced auto
deduction very appealing (for reasons that others on this thread have
elaborated), but am actively uninterested in the abbreviated template
syntax. It seems to me to offer only a modest improvement in brevity, and
pays for it with a very substantial reduction in readability. That
compromise may be appropriate for lambdas, because brevity is particularly
important inside a single expression, but it seems far less justifiable in
the case of ordinary functions.
I objected the use of `auto` in generic lambda.

But for now, for "consistency", I think the connection
between

auto f(auto, auto) { ... }

and

auto f = [](auto, auto) { ... }

is desired.
--
Zhihao Yuan, ID lichray
The best way to predict the future is to invent it.
___________________________________________________
4BSD -- http://bit.ly/blog4bsd
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Scott Prager
2015-03-04 16:52:50 UTC
Permalink
Great stuff! No more writing *is_tuple* and *is_pair* functions to get
SFINAE overloading. Although, a few things get me...

(sorry, the code formatter isn't working for me right now)

/// TEST
*template<class X>*
*void check(auto&& x) {*
* static_assert(std::is_same<decltype(x), X&&>::value);*
*}*

*template<class X>*
*void check_copy(auto x) {*
* static_assert(std::is_same<decltype(x), X>::value);*
*}*

*//...*

*int one;*
*const int cone = 1;*
*check<int>(1);*
*check<int&>(one);*
*check<const int&>(cone);*

*check_copy<int>(1);*
*check_copy<int>(one);*
*check_copy<int>(cone);*
/// END TEST

So, this check shows that when used as a function parameter,
auto behaves very similarly to auto-initializing a variable.

/// TEST
*std::pair<auto...> p = std::pair<int, int>(1,1);*
*std::pair<auto...> q = std::pair<int&, int&>(one,one);*
*std::pair<auto...> r = std::pair<int&&, int&&>(1,1);*

*template<class X> using P = std::pair<X,X>&;*
*check<P<int>>(p);*
*check<P<int&>>(q);*
*check<P<int&&>>(r);*
/// END TEST

This should that *auto* as a template parameter works consistently in
that *tuple<T>* would bind to a reference or rvlaue as well. I tested
*auto& *and *auto&&* in this context as well, and they match against
references and rvalues like template parameters.

*void check_pair(std::pair<auto&&, auto&&>) { static_assert(true); }*

Particularly, this will only work if passed a *pair<X&&, Y&&> *with
*std::move*...
While it's entirely consistent with the rest of the language, it just
seems odd that *auto* in one instance decays the type and in another
acts like *decltype(auto)*. Not a complaint, just an observation.
Post by Faisal Vali
In the hopes of soliciting constructive feedback, if anyone has the
time or the interest to play with a patched up Clang that implements
enhanced auto deduction & abbreviated template syntax from the
https://github.com/faisalv/clang/tree/enhanced-auto-c%2B%2B1z .
The last line of the README file tells you the subversion revision of
LLVM to use.
--
https://github.com/faisalv/clang/blob/enhanced-auto-c%2B%2B1z/test/CXX/auto/cxx1z-auto-vars-generalized.cpp
--
https://github.com/faisalv/clang/blob/enhanced-auto-c%2B%2B1z/test/CXX/auto/cxx1z-abbreviated-templates.cpp
I would certainly appreciate the feedback!
pair<auto...> f() { return make_pair([] { }, [] { }); }
vector<auto> v = vector<int>();
void f(auto) <=> template<class T> void f(T);
a) The equivalence of templates when it comes to trailing return
types in function pointer parameters is based on the order of the
'auto' that signifies a placeholder, not just the appearance of an
template<class R, class P> void f( R(P) ); // #1
template<class P, class R> void f( R(P) ); // #2 (order of
templ-params flipped)
template<class R, class P> void f( auto (P)->R); // equivalent to
#1, not abbreviated.
void f(auto(auto)); // equivalent to #1
void f(auto (auto) -> auto); // equivalent to #2
// the trailing return type auto
// identifies a
template parameter
template<class R> void f(R(auto); // equivalent to #1
template<class P> void f(auto(P)); // equivalent to #2
b) variadic auto
Once an ellipsis is seen as part of the declarator, all contained
auto placeholders get transformed into parameter packs.
void f(auto (*...)(auto) -> std::tuple<auto, std::pair<auto, auto>...>);
Note there are 4 deducible template parameter packs above.
c) multi abbreviated template declarations
void f(auto), g(auto);
are allowed - the above declares two function templates.
d) template aliases desugar their types *after* each auto has been
identified as a placeholder (and so must be deduced)
template<class T> using Int = int;
Int<auto> i = 3; // Is an error, auto must be deducible.
void f(int (*)(int) = [](auto a) { return a; }, auto b = decltype(b){});
f<float*>(); // OK
template<class T> pair<auto...> (*vfp)(auto...) = [](T t1, T* t2)
{ return make_pair(t1, t2); };
Thanks!
Faisal Vali
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Nicol Bolas
2015-03-05 23:19:18 UTC
Permalink
I... just... ugh.

I'm fine with type deduction patterns like std::vector<auto> = ...; That's
just a generalization of type deduction in static contexts.

My issue is with, well, any syntax that declares a template without having
to type either the word "template" or the use of "<>" brackets. Templates
are a fundamentally different kind of construct, and we have specific
syntax for doing so. By removing that syntax, it becomes way too easy to
not notice that you've declared a template.

The last thing we should want is for people to accidentally make something
a template.

I accept this with lambdas, because the main point of lambdas is that
they're a short-cut. Furthermore, they have a syntax that's fundamentally
different from regular functions. But for a regular function? No.

Basically, if I see this:

X func_name(...);

I expect that &func_name ought to return a pointer. For it to do something
else, like being a compiler error, would be surprising.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Ville Voutilainen
2015-03-05 23:36:19 UTC
Permalink
Post by Nicol Bolas
My issue is with, well, any syntax that declares a template without having
to type either the word "template" or the use of "<>" brackets. Templates
are a fundamentally different kind of construct, and we have specific syntax
for doing so. By removing that syntax, it becomes way too easy to not notice
that you've declared a template.
Why is that a problem?
Post by Nicol Bolas
The last thing we should want is for people to accidentally make something a
template.
Same question.
Post by Nicol Bolas
I accept this with lambdas, because the main point of lambdas is that
they're a short-cut. Furthermore, they have a syntax that's fundamentally
different from regular functions. But for a regular function? No.
Ditto.
Post by Nicol Bolas
X func_name(...);
I expect that &func_name ought to return a pointer. For it to do something
else, like being a compiler error, would be surprising.
That already happens if func_name is overloaded, so the terse template
declaration
syntax doesn't introduce that particular problem.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Matthew Fioravante
2015-03-05 23:46:21 UTC
Permalink
Post by Nicol Bolas
I... just... ugh.
I'm fine with type deduction patterns like std::vector<auto> = ...; That's
just a generalization of type deduction in static contexts.
My issue is with, well, any syntax that declares a template without having
to type either the word "template" or the use of "<>" brackets. Templates
are a fundamentally different kind of construct, and we have specific
syntax for doing so. By removing that syntax, it becomes way too easy to
not notice that you've declared a template.
You could add a requirement for an empty template <> when using auto.

template <>
auto add(auto x, auto y) { return x + y; }
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Klaim - Joël Lamotte
2015-03-05 23:53:56 UTC
Permalink
​I don't see the point in adding such requirement for people who don't
consider it a problem
(me included). My understanding is that the proposal provide several ways
to say aproximatively
the same thing and you can easily chose the level of details that suits
your viewpoint.
I think it's better that way.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Richard Smith
2015-03-06 00:12:18 UTC
Permalink
Post by Matthew Fioravante
Post by Nicol Bolas
I... just... ugh.
I'm fine with type deduction patterns like std::vector<auto> = ...;
That's just a generalization of type deduction in static contexts.
My issue is with, well, any syntax that declares a template without
having to type either the word "template" or the use of "<>" brackets.
Templates are a fundamentally different kind of construct, and we have
specific syntax for doing so. By removing that syntax, it becomes way too
easy to not notice that you've declared a template.
You could add a requirement for an empty template <> when using auto.
template <>
auto add(auto x, auto y) { return x + y; }
... except that "template <>" currently always introduces a non-template,
and generally follows non-template rules (can be defined outside of the
header, etc). I don't think that solves the problem.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Herb Sutter
2015-03-06 00:24:06 UTC
Permalink
To paraphrase Stroustrup, it’s not about functional programming and object-oriented programming and generic programming
 “it’s all just programming.”
Post by Nicol Bolas
Templates are a fundamentally different kind of construct
Why? Every full specialization of a function template is just a function.
Post by Nicol Bolas
My issue is with, well, any syntax that declares a template without having to type either the word "template" or the use of "<>" brackets.
That ship has sailed:

auto plus = [](auto x, auto y) { return x+y; }

which even already decays to an ordinary pointer to function, etc.

Clarifying Q: Are we mainly arguing about whether to require the three characters =, [, and ] ?

Not only has the ship sailed, but I for one like the direction it’s sailing. I see no reason why functions should be forced to spell “template” and “<>”. What value does it add? It’s “just programming.” In fact, if we didn’t have backward compatibility issues with unnamed parameters and such, I’d personally probably be fine with just “auto plus(x,y){x+y}” as an equivalent function definition. That still doesn’t lose any information.

Gratuitous syntax is often unnecessary and usually harmful. Saying

template<class T, class U>
auto(T x, U y) -> decltype(x+y) { return x+y; }

does not appear to me to contain any more information than

auto plus(auto x, auto y) { return x+y; }

does it? Requiring the verbose syntax is gratuitous, if the verbose syntax does not add information, does not serve to disambiguate anything, and does not highlight a dangerous operation or anything else I can see that deserves to have attention called to it.

There’s a disturbing (to me and at least some others) trend in C++ these days: People seem to be very prone to wanting “more syntax” lately. It’s rather Vasa-like, if only lexically. Let me channel certain influential committee members and say: ‘People these days are always asking for more syntax! There’s no proposal they’ve seen that they couldn’t make uglier with more syntax!’

Important note: The point here is NOT terseness for terseness’ sake. I am not arguing that terser is somehow better, that terseness is virtuous in itself. Too many people glorify languages because they’re terser; fewer characters alone doesn’t make code clearer. Rather, my point is to avoid gratuitous verbosity. At the other end of the pendulum, too many people glorify verbose syntax because they think _that_ is somehow inherently clearer; usually it isn’t. So I am arguing that neither is verbosity virtuous in itself.

Herb


From: Nicol Bolas [mailto:***@gmail.com]
Sent: Thursday, March 5, 2015 3:19 PM
To: std-***@isocpp.org
Cc: std-***@isocpp.org; c++std-***@accu.org; ***@gmail.com
Subject: [c++std-core-27204] Re: An implementation of enhanced auto deduction and abbreviated template syntax using Clang

I... just... ugh.

I'm fine with type deduction patterns like std::vector<auto> = ...; That's just a generalization of type deduction in static contexts.

My issue is with, well, any syntax that declares a template without having to type either the word "template" or the use of "<>" brackets. Templates are a fundamentally different kind of construct, and we have specific syntax for doing so. By removing that syntax, it becomes way too easy to not notice that you've declared a template.

The last thing we should want is for people to accidentally make something a template.

I accept this with lambdas, because the main point of lambdas is that they're a short-cut. Furthermore, they have a syntax that's fundamentally different from regular functions. But for a regular function? No.

Basically, if I see this:

X func_name(...);

I expect that &func_name ought to return a pointer. For it to do something else, like being a compiler error, would be surprising.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
'Richard Smith' via ISO C++ Standard - Discussion
2015-03-06 01:01:24 UTC
Permalink
Post by Herb Sutter
To paraphrase Stroustrup, it’s not about functional programming and
object-oriented programming and generic programming
 “it’s all *just
programming*.”
Post by Nicol Bolas
Templates are a fundamentally different kind of construct
Why? Every full specialization of a function template is just a function.
Post by Nicol Bolas
My issue is with, well, any syntax that declares a template without
having to type either the word "template" or the use of "<>" brackets.
auto plus = [](auto x, auto y) { return x+y; }
which even already decays to an ordinary pointer to function, etc.
Clarifying Q: Are we mainly arguing about whether to require the three
characters =, [, and ] ?
Not only has the ship sailed, but I for one like the direction it’s
sailing. I see no reason why functions should be forced to spell “template”
and “<>”. What value does it add? It’s “just programming.” In fact, if we
didn’t have backward compatibility issues with unnamed parameters and such,
I’d personally probably be fine with just “auto plus(x,y){x+y}” as an
equivalent function definition. That still doesn’t lose any information.
Gratuitous syntax is often unnecessary and usually harmful. Saying
template<class T, class U>
auto(T x, U y) -> decltype(x+y) { return x+y; }
does not appear to me to contain any more information than
auto plus(auto x, auto y) { return x+y; }
does it?
To me, yes, it does. It says:

* I deliberately want to allow the parameters to have different types
* I deliberately want to allow the return type to differ from those types
* I want a substitution failure if x + y is not valid (your rewrite is
possibly incorrect due to this)
* I want to "perfectly return" x + y rather than always returning by value
(your rewrite is possibly incorrect due to this)
* It's OK for this apparent function definition to be in a header file
despite not including the 'inline' keyword
* It's *not* OK to move this definition out of the header file.
* And the big one: it says "this is a template". No need to go scanning
the declaration for "auto" (or for concept names, not that you can identify
them by sight). It's right there at the start.

It's somewhat less clear to me how this loss of readability balances
against the possibility of improved readability from a shorter declaration.

Requiring the verbose syntax is gratuitous, if the verbose syntax does not
Post by Herb Sutter
add information, does not serve to disambiguate anything, and does not
highlight a dangerous operation or anything else I can see that deserves to
have attention called to it.
There’s a disturbing (to me and at least some others) trend in C++ these
days: People seem to be very prone to wanting “more syntax” lately. It’s
rather Vasa-like, if only lexically. Let me channel certain influential
committee members and say: ‘People these days are always asking for more
syntax! There’s no proposal they’ve seen that they couldn’t make uglier
with more syntax!’
Important note: The point here is NOT terseness for terseness’ sake. I am
not arguing that terser is somehow better, that terseness is virtuous in
itself. Too many people glorify languages because they’re terser; fewer
characters alone doesn’t make code clearer. Rather, my point is to avoid
gratuitous verbosity. At the other end of the pendulum, too many people
glorify verbose syntax because they think _that_ is somehow inherently
clearer; usually it isn’t. So I am arguing that neither is verbosity
virtuous in itself.
Right; we need to find a balance where the syntax we have is neither
unnecessarily terse (to the point of causing readability and maintenance
problems) nor unnecessarily verbose. It is up to the people proposing the
change to demonstrate that this requirement is met, and the reactions on
this thread seem to suggest that we are, so far, lacking a good argument
that the proposed syntax meets the Goldilocks criterion.

Herb
Post by Herb Sutter
*Sent:* Thursday, March 5, 2015 3:19 PM
*Subject:* [c++std-core-27204] Re: An implementation of enhanced auto
deduction and abbreviated template syntax using Clang
I... just... ugh.
I'm fine with type deduction patterns like std::vector<auto> = ...; That's
just a generalization of type deduction in static contexts.
My issue is with, well, any syntax that declares a template without having
to type either the word "template" or the use of "<>" brackets. Templates
are a fundamentally different kind of construct, and we have specific
syntax for doing so. By removing that syntax, it becomes way too easy to
not notice that you've declared a template.
The last thing we should want is for people to accidentally make something a template.
I accept this with lambdas, because the main point of lambdas is that
they're a short-cut. Furthermore, they have a syntax that's fundamentally
different from regular functions. But for a regular function? No.
X func_name(...);
I expect that &func_name ought to return a pointer. For it to do something
else, like being a compiler error, would be surprising.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Richard Smith
2015-03-06 01:08:16 UTC
Permalink
On 5 Mar 2015 5:01 pm, "'Richard Smith' via ISO C++ Standard - Discussion" <
Post by 'Richard Smith' via ISO C++ Standard - Discussion
Post by Herb Sutter
To paraphrase Stroustrup, it’s not about functional programming and
object-oriented programming and generic programming
 “it’s all just
programming.”
Post by 'Richard Smith' via ISO C++ Standard - Discussion
Post by Herb Sutter
Post by Nicol Bolas
Templates are a fundamentally different kind of construct
Why? Every full specialization of a function template is just a function.
Post by Nicol Bolas
My issue is with, well, any syntax that declares a template without
having to type either the word "template" or the use of "<>" brackets.
Post by 'Richard Smith' via ISO C++ Standard - Discussion
Post by Herb Sutter
auto plus = [](auto x, auto y) { return x+y; }
which even already decays to an ordinary pointer to function, etc.
Clarifying Q: Are we mainly arguing about whether to require the three
characters =, [, and ] ?
Post by 'Richard Smith' via ISO C++ Standard - Discussion
Post by Herb Sutter
Not only has the ship sailed, but I for one like the direction it’s
sailing. I see no reason why functions should be forced to spell “template”
and “<>”. What value does it add? It’s “just programming.” In fact, if we
didn’t have backward compatibility issues with unnamed parameters and such,
I’d personally probably be fine with just “auto plus(x,y){x+y}” as an
equivalent function definition. That still doesn’t lose any information.
Post by 'Richard Smith' via ISO C++ Standard - Discussion
Post by Herb Sutter
Gratuitous syntax is often unnecessary and usually harmful. Saying
template<class T, class U>
auto(T x, U y) -> decltype(x+y) { return x+y; }
does not appear to me to contain any more information than
auto plus(auto x, auto y) { return x+y; }
does it?
* I deliberately want to allow the parameters to have different types
* I deliberately want to allow the return type to differ from those types
* I want a substitution failure if x + y is not valid (your rewrite is
possibly incorrect due to this)
Post by 'Richard Smith' via ISO C++ Standard - Discussion
* I want to "perfectly return" x + y rather than always returning by
value (your rewrite is possibly incorrect due to this)
Post by 'Richard Smith' via ISO C++ Standard - Discussion
* It's OK for this apparent function definition to be in a header file
despite not including the 'inline' keyword
Post by 'Richard Smith' via ISO C++ Standard - Discussion
* It's *not* OK to move this definition out of the header file.
* And the big one: it says "this is a template". No need to go scanning
the declaration for "auto" (or for concept names, not that you can identify
them by sight). It's right there at the start.
Post by 'Richard Smith' via ISO C++ Standard - Discussion
It's somewhat less clear to me how this loss of readability balances
against the possibility of improved readability from a shorter declaration.
Post by 'Richard Smith' via ISO C++ Standard - Discussion
Post by Herb Sutter
Requiring the verbose syntax is gratuitous, if the verbose syntax does
not add information, does not serve to disambiguate anything, and does not
highlight a dangerous operation or anything else I can see that deserves to
have attention called to it.
Post by 'Richard Smith' via ISO C++ Standard - Discussion
Post by Herb Sutter
There’s a disturbing (to me and at least some others) trend in C++ these
days: People seem to be very prone to wanting “more syntax” lately. It’s
rather Vasa-like, if only lexically. Let me channel certain influential
committee members and say: ‘People these days are always asking for more
syntax! There’s no proposal they’ve seen that they couldn’t make uglier
with more syntax!’
Post by 'Richard Smith' via ISO C++ Standard - Discussion
Post by Herb Sutter
Important note: The point here is NOT terseness for terseness’ sake. I
am not arguing that terser is somehow better, that terseness is virtuous in
itself. Too many people glorify languages because they’re terser; fewer
characters alone doesn’t make code clearer. Rather, my point is to avoid
gratuitous verbosity. At the other end of the pendulum, too many people
glorify verbose syntax because they think _that_ is somehow inherently
clearer; usually it isn’t. So I am arguing that neither is verbosity
virtuous in itself.
Post by 'Richard Smith' via ISO C++ Standard - Discussion
Right; we need to find a balance where the syntax we have is neither
unnecessarily terse (to the point of causing readability and maintenance
problems) nor unnecessarily verbose. It is up to the people proposing the
change to demonstrate that this requirement is met, and the reactions on
this thread seem to suggest that we are, so far, lacking a good argument
that the proposed syntax meets the Goldilocks criterion.

Incidentally, this is one thing I love about the concepts TS: it lets us
form a much stronger argument about the merits here based on actual user
experience.
Post by 'Richard Smith' via ISO C++ Standard - Discussion
Post by Herb Sutter
Herb
Sent: Thursday, March 5, 2015 3:19 PM
Subject: [c++std-core-27204] Re: An implementation of enhanced auto
deduction and abbreviated template syntax using Clang
Post by 'Richard Smith' via ISO C++ Standard - Discussion
Post by Herb Sutter
I... just... ugh.
I'm fine with type deduction patterns like std::vector<auto> = ...;
That's just a generalization of type deduction in static contexts.
Post by 'Richard Smith' via ISO C++ Standard - Discussion
Post by Herb Sutter
My issue is with, well, any syntax that declares a template without
having to type either the word "template" or the use of "<>" brackets.
Templates are a fundamentally different kind of construct, and we have
specific syntax for doing so. By removing that syntax, it becomes way too
easy to not notice that you've declared a template.
Post by 'Richard Smith' via ISO C++ Standard - Discussion
Post by Herb Sutter
The last thing we should want is for people to accidentally make something a template.
I accept this with lambdas, because the main point of lambdas is that
they're a short-cut. Furthermore, they have a syntax that's fundamentally
different from regular functions. But for a regular function? No.
Post by 'Richard Smith' via ISO C++ Standard - Discussion
Post by Herb Sutter
X func_name(...);
I expect that &func_name ought to return a pointer. For it to do
something else, like being a compiler error, would be surprising.
Post by 'Richard Smith' via ISO C++ Standard - Discussion
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
Post by 'Richard Smith' via ISO C++ Standard - Discussion
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Scott Prager
2015-03-06 01:30:55 UTC
Permalink
Post by Herb Sutter
Gratuitous syntax is often unnecessary and usually harmful. Saying
Post by Herb Sutter
template<class T, class U>
auto(T x, U y) -> decltype(x+y) { return x+y; }
does not appear to me to contain any more information than
auto plus(auto x, auto y) { return x+y; }
does it?
* I deliberately want to allow the parameters to have different types
* I deliberately want to allow the return type to differ from those types
Does that mean that the version using auto *accidentally* allows the
arguments to have different types, and return a different type?
Post by Herb Sutter
* I want a substitution failure if x + y is not valid (your rewrite is
possibly incorrect due to this)
* I want to "perfectly return" x + y rather than always returning by value
Post by Herb Sutter
(your rewrite is possibly incorrect due to this)
* It's OK for this apparent function definition to be in a header file
Post by Herb Sutter
despite not including the 'inline' keyword
Does the use of *auto* as a parameter not also convey that? If it's treated
consistently like a template function, I'd think it should.
Post by Herb Sutter
* It's *not* OK to move this definition out of the header file.
Use of *auto* as a return type implies that, since the definition must be
in the TU.
Post by Herb Sutter
* And the big one: it says "this is a template". No need to go scanning
the declaration for "auto" (or for concept names, not that you can identify
them by sight). It's right there at the start.
It's somewhat less clear to me how this loss of readability balances
against the possibility of improved readability from a shorter declaration.
Requiring the verbose syntax is gratuitous, if the verbose syntax does not
Post by Herb Sutter
add information, does not serve to disambiguate anything, and does not
highlight a dangerous operation or anything else I can see that deserves to
have attention called to it.
There’s a disturbing (to me and at least some others) trend in C++ these
days: People seem to be very prone to wanting “more syntax” lately. It’s
rather Vasa-like, if only lexically. Let me channel certain influential
committee members and say: ‘People these days are always asking for more
syntax! There’s no proposal they’ve seen that they couldn’t make uglier
with more syntax!’
Important note: The point here is NOT terseness for terseness’ sake. I am
not arguing that terser is somehow better, that terseness is virtuous in
itself. Too many people glorify languages because they’re terser; fewer
characters alone doesn’t make code clearer. Rather, my point is to avoid
gratuitous verbosity. At the other end of the pendulum, too many people
glorify verbose syntax because they think _that_ is somehow inherently
clearer; usually it isn’t. So I am arguing that neither is verbosity
virtuous in itself.
Right; we need to find a balance where the syntax we have is neither
unnecessarily terse (to the point of causing readability and maintenance
problems) nor unnecessarily verbose. It is up to the people proposing the
change to demonstrate that this requirement is met, and the reactions on
this thread seem to suggest that we are, so far, lacking a good argument
that the proposed syntax meets the Goldilocks criterion.
Herb
Post by Herb Sutter
*Sent:* Thursday, March 5, 2015 3:19 PM
*Subject:* [c++std-core-27204] Re: An implementation of enhanced auto
deduction and abbreviated template syntax using Clang
I... just... ugh.
I'm fine with type deduction patterns like std::vector<auto> = ...;
That's just a generalization of type deduction in static contexts.
My issue is with, well, any syntax that declares a template without
having to type either the word "template" or the use of "<>" brackets.
Templates are a fundamentally different kind of construct, and we have
specific syntax for doing so. By removing that syntax, it becomes way too
easy to not notice that you've declared a template.
The last thing we should want is for people to accidentally make something a template.
I accept this with lambdas, because the main point of lambdas is that
they're a short-cut. Furthermore, they have a syntax that's fundamentally
different from regular functions. But for a regular function? No.
X func_name(...);
I expect that &func_name ought to return a pointer. For it to do
something else, like being a compiler error, would be surprising.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Nathan Ernst
2015-03-06 01:32:37 UTC
Permalink
Post by 'Richard Smith' via ISO C++ Standard - Discussion
* I deliberately want to allow the parameters to have different types
Using auto in this context does not preclude this, if anything it makes
indicating you expect the same type harder (impossible?).

* I deliberately want to allow the return type to differ from those types

Again, I don't see how this is different from the prior argument. Using
decltype(a + b) makes it explicit about expectations of the argument types
and the return type, but it gives zero guarantees that the return type is
same as either 'a' or 'b'.

* I want a substitution failure if x + y is not valid (your rewrite is
Post by 'Richard Smith' via ISO C++ Standard - Discussion
possibly incorrect due to this)
This may be a cause for concern, I have no argument/solution to it.

* I want to "perfectly return" x + y rather than always returning by value
Post by 'Richard Smith' via ISO C++ Standard - Discussion
(your rewrite is possibly incorrect due to this)
I think this may be a red herring. To perfectly return, wouldn't at least
one of the arguments have to be perfectly forwarded? If so, which one? 'x'
or 'y' or either? Even then, aren't there facilities to detect such
situations already?\

* It's OK for this apparent function definition to be in a header file
Post by 'Richard Smith' via ISO C++ Standard - Discussion
despite not including the 'inline' keyword
As it would be a templated function, yes, as every other template function
is currently.
Post by 'Richard Smith' via ISO C++ Standard - Discussion
* It's *not* OK to move this definition out of the header file.
For the same reason you can't move a templated function definition out of a
header currently (or at least out of a scope where all instantiations need
to be known).

* And the big one: it says "this is a template". No need to go scanning
Post by 'Richard Smith' via ISO C++ Standard - Discussion
the declaration for "auto" (or for concept names, not that you can identify
them by sight). It's right there at the start.
I don't really have an argument for this, at all. I can see the value
you're asking for. Personally, I would hope to see utilization of this
feature more in end-user code, not in libraries. I would hope, and rather,
library writers would take the more verbose route utilizing SFINAE &
concepts (when available) to give more meaningful errors on incorrect usage.

It's somewhat less clear to me how this loss of readability balances
Post by 'Richard Smith' via ISO C++ Standard - Discussion
against the possibility of improved readability from a shorter declaration.
Already, once you've gotten yourself into template metaprogramming land,
you already have to run on your 'spidey sense' to determine what's going
on. As far as searching code, I've rarely seen 'template' on the same line
as the function being defined/declared, and it's even worse if you're
looking for a templated member function on a templated class.

All this being said, I don't see anything proposed that prevents you from
using the more verbose syntax. And, arguably, I'd like to see the more
verbose syntax when I'm utilizing a library, at least in so far as
expectations of arguments and returns. I expect this very vague syntax to
be at the "end-user" application level or "glue" level.

-Nate

On Thu, Mar 5, 2015 at 7:01 PM, 'Richard Smith' via ISO C++ Standard -
Post by 'Richard Smith' via ISO C++ Standard - Discussion
Post by Herb Sutter
To paraphrase Stroustrup, it’s not about functional programming and
object-oriented programming and generic programming
 “it’s all *just
programming*.”
Post by Nicol Bolas
Templates are a fundamentally different kind of construct
Why? Every full specialization of a function template is just a function.
Post by Nicol Bolas
My issue is with, well, any syntax that declares a template without
having to type either the word "template" or the use of "<>" brackets.
auto plus = [](auto x, auto y) { return x+y; }
which even already decays to an ordinary pointer to function, etc.
Clarifying Q: Are we mainly arguing about whether to require the three
characters =, [, and ] ?
Not only has the ship sailed, but I for one like the direction it’s
sailing. I see no reason why functions should be forced to spell “template”
and “<>”. What value does it add? It’s “just programming.” In fact, if we
didn’t have backward compatibility issues with unnamed parameters and such,
I’d personally probably be fine with just “auto plus(x,y){x+y}” as an
equivalent function definition. That still doesn’t lose any information.
Gratuitous syntax is often unnecessary and usually harmful. Saying
template<class T, class U>
auto(T x, U y) -> decltype(x+y) { return x+y; }
does not appear to me to contain any more information than
auto plus(auto x, auto y) { return x+y; }
does it?
* I deliberately want to allow the parameters to have different types
* I deliberately want to allow the return type to differ from those types
* I want a substitution failure if x + y is not valid (your rewrite is
possibly incorrect due to this)
* I want to "perfectly return" x + y rather than always returning by
value (your rewrite is possibly incorrect due to this)
* It's OK for this apparent function definition to be in a header file
despite not including the 'inline' keyword
* It's *not* OK to move this definition out of the header file.
* And the big one: it says "this is a template". No need to go scanning
the declaration for "auto" (or for concept names, not that you can identify
them by sight). It's right there at the start.
It's somewhat less clear to me how this loss of readability balances
against the possibility of improved readability from a shorter declaration.
Requiring the verbose syntax is gratuitous, if the verbose syntax does not
Post by Herb Sutter
add information, does not serve to disambiguate anything, and does not
highlight a dangerous operation or anything else I can see that deserves to
have attention called to it.
There’s a disturbing (to me and at least some others) trend in C++ these
days: People seem to be very prone to wanting “more syntax” lately. It’s
rather Vasa-like, if only lexically. Let me channel certain influential
committee members and say: ‘People these days are always asking for more
syntax! There’s no proposal they’ve seen that they couldn’t make uglier
with more syntax!’
Important note: The point here is NOT terseness for terseness’ sake. I am
not arguing that terser is somehow better, that terseness is virtuous in
itself. Too many people glorify languages because they’re terser; fewer
characters alone doesn’t make code clearer. Rather, my point is to avoid
gratuitous verbosity. At the other end of the pendulum, too many people
glorify verbose syntax because they think _that_ is somehow inherently
clearer; usually it isn’t. So I am arguing that neither is verbosity
virtuous in itself.
Right; we need to find a balance where the syntax we have is neither
unnecessarily terse (to the point of causing readability and maintenance
problems) nor unnecessarily verbose. It is up to the people proposing the
change to demonstrate that this requirement is met, and the reactions on
this thread seem to suggest that we are, so far, lacking a good argument
that the proposed syntax meets the Goldilocks criterion.
Herb
Post by Herb Sutter
*Sent:* Thursday, March 5, 2015 3:19 PM
*Subject:* [c++std-core-27204] Re: An implementation of enhanced auto
deduction and abbreviated template syntax using Clang
I... just... ugh.
I'm fine with type deduction patterns like std::vector<auto> = ...;
That's just a generalization of type deduction in static contexts.
My issue is with, well, any syntax that declares a template without
having to type either the word "template" or the use of "<>" brackets.
Templates are a fundamentally different kind of construct, and we have
specific syntax for doing so. By removing that syntax, it becomes way too
easy to not notice that you've declared a template.
The last thing we should want is for people to accidentally make something a template.
I accept this with lambdas, because the main point of lambdas is that
they're a short-cut. Furthermore, they have a syntax that's fundamentally
different from regular functions. But for a regular function? No.
X func_name(...);
I expect that &func_name ought to return a pointer. For it to do
something else, like being a compiler error, would be surprising.
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Andrew Sutton
2015-03-06 02:45:20 UTC
Permalink
Post by 'Richard Smith' via ISO C++ Standard - Discussion
Right; we need to find a balance where the syntax we have is neither
unnecessarily terse (to the point of causing readability and maintenance
problems) nor unnecessarily verbose. It is up to the people proposing the
change to demonstrate that this requirement is met, and the reactions on
this thread seem to suggest that we are, so far, lacking a good argument
that the proposed syntax meets the Goldilocks criterion.
I don't think that there is a single "just right" syntax. Some
declarations simply require heavier syntax (although the template
introduction syntax was added to alleviate some of that). Other
declarations should be able to be expressed simply and directly,
without extra notation.

There is a balance to be reached, but programmers need to find that
for themselves before pre-judging the syntax.

Andrew
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Bjarne Stroustrup
2015-03-06 03:05:39 UTC
Permalink
(1) people always ask for heavier syntax from new features
(2) people learn
(3) people always complain that the syntax they insisted on is too heavy
handed

I remember serious and well-meaning criticism that allowing "sqrt(2)"
would lead to misuse and bugs and that it was *good* for people and
especially for maintenance if people had to write "sqrt(2.)" or
"sqrt((double)2)" to avoid crashes.

Yes, someone is going to write "void f(auto);" and be surprised. In
particular, someone is going to write "void ff(auto,auto);" and be
surprised that "ff("hello",2)" is allowed, but I think that ship has
sailed. What we really have to get into our/people's heads is that
"auto" is just the weakest constraint. Even a concept that requires
nothing is stronger because "void ff(Unconstrained, Unconstrained);"
will not accept "ff("hello",2)". There are examples that are better
expressed using the less terse notations. We will eventually settle on
conventions for use.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Herb Sutter
2015-03-06 04:19:38 UTC
Permalink
Exactly.

Also, the populations of (1) and (3) are different sizes: I can roughly count the number of people (1) I've heard complain that (existing or proposed) C++ syntax is not verbose enough and should be longer, usually in forums like these. I cannot begin to count the number of people (3) I've heard complain that C++ syntax is needlessly verbose, based on their personal experience using the language in their day jobs, usually in comparison with similar features in other languages.
Post by Bjarne Stroustrup
What we really have
to get into our/people's heads is that "auto" is just the weakest constraint.
Even a concept that requires nothing is stronger because "void
ff(Unconstrained, Unconstrained);" will not accept "ff("hello",2)".
Exactly. Everywhere you see "auto" today, you'll see a concept name tomorrow (if approved). And I think the argument that you wouldn't want to write "auto foo( auto )" definitively evaporates once it's "Concept1 foo( Concept2 x )", and that's the road we're on.

Of all the features proposed for C++17 or 20, I think it's already clear concepts will have the largest effect on the way we write new code. And I think we don't yet quite grok just how broad that effect will be -- I expect most new function templates will routinely use them, but even more than that I suspect that five years from now many (though probably not most) new local variable declarations will likely be typed using concept names, and that right there is a lot of LOC. But the effect could be broader still, so it's good we're going to start getting that experience.

Herb
Post by Bjarne Stroustrup
-----Original Message-----
Sent: Thursday, March 5, 2015 7:06 PM
Subject: [c++std-core-27217] Re: An implementation of enhanced auto
deduction and abbreviated template syntax using Clang
(1) people always ask for heavier syntax from new features
(2) people learn
(3) people always complain that the syntax they insisted on is too heavy
handed
I remember serious and well-meaning criticism that allowing "sqrt(2)"
would lead to misuse and bugs and that it was *good* for people and
especially for maintenance if people had to write "sqrt(2.)" or
"sqrt((double)2)" to avoid crashes.
Yes, someone is going to write "void f(auto);" and be surprised. In particular,
someone is going to write "void ff(auto,auto);" and be surprised that
"ff("hello",2)" is allowed, but I think that ship has sailed. What we really have
to get into our/people's heads is that "auto" is just the weakest constraint.
Even a concept that requires nothing is stronger because "void
ff(Unconstrained, Unconstrained);"
will not accept "ff("hello",2)". There are examples that are better expressed
using the less terse notations. We will eventually settle on conventions for
use.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Tom Honermann
2015-03-06 04:44:56 UTC
Permalink
Post by Bjarne Stroustrup
(1) people always ask for heavier syntax from new features
(2) people learn
(3) people always complain that the syntax they insisted on is too heavy
handed
I think there is truth in that. However, I think some other languages
have demonstrated the opposite problem. For example, Perl has been
criticized (fairly or not, I'm not judging) for allowing overly terse
syntax and sometimes termed a "write-only language" due to a common
perception that maintaining Perl code is difficult as a result. I'm not
trying to defend that argument here, just pointing out that the
perception exists.

I think the abbreviated syntax goes too far as currently proposed. It
is hard to imagine a more terse syntax that doesn't require dropping
type placeholders completely. I stated elsewhere in this thread that I
don't mind the current, rather heavy, template syntax, but that doesn't
mean that I wouldn't appreciate a lighter syntax. If there were not
significant semantic differences between template function definitions
and non-template function definitions, then I would love the abbreviated
syntax. The fact is though, that there are significant semantic
differences and some of them are quite subtle.

I don't feel concerned about point of usage of functions declared with
the abbreviated syntax. The behavioral differences aren't that great in
that case. My concern is with maintenance of functions declared with
this syntax and maintainers not realizing that a template is being
modified. Richard supplied an excellent list a few emails back
illustrating some of the problems one can encounter switching a simple
traditionally declared template function to an abbreviated one. I think
his insights should not be overlooked here (or, anywhere else, really).

I would be quite happy with the smallest addition to the proposal that
makes it clear that "this is a template function" and that doesn't rely
on my ability to scan for 'auto' or identify the name of a concept in
the parameter list.

We have this for lambdas:
auto l = [](auto x) { return x; }
If we could do (something like) these for generic functions, I would be
thrilled:
auto <>f(auto x) { return x; }
auto <>f(Iterator i) { return i; }

Tom.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Faisal Vali
2015-03-06 05:01:46 UTC
Permalink
<snip>

* And the big one: it says "this is a template". No need to go scanning the
declaration for "auto" (or for concept names, not that you can identify them
by sight). It's right there at the start.
It's somewhat less clear to me how this loss of readability balances against
the possibility of improved readability from a shorter declaration.
+1.

How this fundamental syntactic tension shall resolve itself in time is
a futurity I wish I could claim authority on.

I confess, when *reading* code, I currently prefer to see the template
header to 'warn' me that a template is about to follow (just as i
usually prefer to *read* the type-name when variables are declared) -
but, given this thread, I wonder whether I should require that warning
- and whether it is simply an inertia that serves little useful
purpose. If I am allowed a touch of hyperbole, my worst fear is that
my use of abbreviated syntax shall be inconsistently driven by the
vagaries of an occasionally undisciplineable mood.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Nicol Bolas
2015-03-06 17:21:16 UTC
Permalink
Post by Herb Sutter
To paraphrase Stroustrup, it’s not about functional programming and
object-oriented programming and generic programming
 “it’s all *just
programming*.”
Post by Nicol Bolas
Templates are a fundamentally different kind of construct
Why? Every full specialization of a function template is just a function.
OK, let's explore this.

Let's say that I'm a novice C++ programmer. I don't really know much about
the language. But I have some basic knowledge.

Now, I've been told that when I write functions, I put a prototype in a
header file so that other people can use it. But I also put the
implementation in a source file, so that it stays hidden. So I write:

//header
RetType func_name(Type1 arg1, ...);

//source
RetType func_name(Type1 arg1, ...)
{
//implementation
}


OK, fine.

I've also been told about a different class of functions: template
functions. For reasons I haven't been told and don't much care about (since
I'm a novice), I have to put the implementation in the header file. So I
know that if I type the word "template", then that function's
implementation has to go into a header. So I always do this:

//header
template<typename T>
RetType func_name_template(T arg1, ...)
{
//implementation
}

//source doesn't exist.


OK, fine. So... explain to me, the novice C++ programmer, why this doesn't
work:

//header
RetType func_name_concept(ConceptName arg1, ...);

//source
RetType func_name_concept(ConceptName arg1, ...)
{
//implementation
}

Explain to me, the novice C++ programmer, why this thing which doesn't look
like a template suddenly *became* a template. Explain to me why I have to
implement it in a header, even though it looks exactly like every other
non-template function declaration/definition.

To the novice C++ programmer, it *isn't* "all just programming." Whether
something is a template *matters*.

Oh, you could say, "well just put *everything* in a header." That's...
insane. Compile times for C++ projects of significant size are already huge
even when you try to only put what you need in headers. Adding the burden
of shoving everything in a header is crazy.

Now, if you can promise me that the same version of C++ that will include
this terse syntax will also include *modules*, I will immediately stop
caring. Once that exists, then most of the differences between template and
non-template functions will be erased. And therefore, so too can the
syntactic differences.

But so long as there is a difference in how you implement template and
non-template functions, I say that there should be an obvious difference in
syntax too.
Post by Herb Sutter
Post by Nicol Bolas
My issue is with, well, any syntax that declares a template without
having to type either the word "template" or the use of "<>" brackets.
auto plus = [](auto x, auto y) { return x+y; }
which even already decays to an ordinary pointer to function, etc.
That doesn't decay into a function pointer. It can't; the operator() is a
template.
Post by Herb Sutter
Clarifying Q: Are we mainly arguing about whether to require the three
characters =, [, and ] ?
Except that there is a difference between creating a lambda (which creates
a functor) and creating a function (which can be overloaded).
Post by Herb Sutter
Not only has the ship sailed, but I for one like the direction it’s
sailing. I see no reason why functions should be forced to spell “template”
and “<>”. What value does it add? It’s “just programming.” In fact, if we
didn’t have backward compatibility issues with unnamed parameters and such,
I’d personally probably be fine with just “auto plus(x,y){x+y}” as an
equivalent function definition. That still doesn’t lose any information.
Gratuitous syntax is often unnecessary and usually harmful. Saying
template<class T, class U>
auto(T x, U y) -> decltype(x+y) { return x+y; }
does not appear to me to contain any more information than
auto plus(auto x, auto y) { return x+y; }
does it?
If you take out the late specified return type (I specifically said that
static deduction was fine), then I don't see the problem with the first one.
Post by Herb Sutter
Requiring the verbose syntax is gratuitous, if the verbose syntax does not
add information, does not serve to disambiguate anything, and does not
highlight a dangerous operation or anything else I can see that deserves to
have attention called to it.
There’s a disturbing (to me and at least some others) trend in C++ these
days: People seem to be very prone to wanting “more syntax” lately. It’s
rather Vasa-like, if only lexically. Let me channel certain influential
committee members and say: ‘People these days are always asking for more
syntax! There’s no proposal they’ve seen that they couldn’t make uglier
with more syntax!’
Important note: The point here is NOT terseness for terseness’ sake. I am
not arguing that terser is somehow better, that terseness is virtuous in
itself. Too many people glorify languages because they’re terser; fewer
characters alone doesn’t make code clearer. Rather, my point is to avoid
gratuitous verbosity. At the other end of the pendulum, too many people
glorify verbose syntax because they think _that_ is somehow inherently
clearer; usually it isn’t. So I am arguing that neither is verbosity
virtuous in itself.
Herb
The virtue to me of the large syntax of templates is this:

Templates have to be treated differently from non-templates. They have
different needs of where their implementations live. And because of those
needs, templates make your code compile slower. Even ignoring the
compile-time cost of template instantiation, your source has to go in the
header. And if that header is included in more than one place, then the
source for that template must be recompiled for every place it is included.

Therefore, the bulky template syntax pokes you in the eye every time you
write something that's going to compile slower. It immediately lets you
know that this function operates under fundamentally different rules than
regular functions.

Again, if you could guarantee that we get modules alongside this syntax,
I'd be fine, since using templates will not hurt your compile times nearly
as much.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Jonathan Wakely
2015-03-06 17:37:53 UTC
Permalink
Post by Nicol Bolas
Explain to me, the novice C++ programmer, why this thing which doesn't look
like a template suddenly became a template. Explain to me why I have to
implement it in a header, even though it looks exactly like every other
non-template function declaration/definition.
To the novice C++ programmer, it isn't "all just programming." Whether
something is a template matters.
Ah, the "won't somebody think of the children" argument.

The answer to why it suddenly became a template is that its parameter
is a concept, not a type. A concept is a family of types. I don't see
why that should be much harder to teach than "a function template is a
family of functions" and "a class template is a family of types".

If we're teaching novices how to write C++ templates based on "just
put template<blah> before it and make sure it's in a header" that
doesn't seem like a very sound basis for learning anything more than
arbitrary syntactic rules and cargo cult programming.

(Is it time to trim the CC list so this doesn't continue to be
cross-posted everywhere?)
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Nicol Bolas
2015-03-06 18:07:06 UTC
Permalink
Post by Jonathan Wakely
Post by Nicol Bolas
Explain to me, the novice C++ programmer, why this thing which doesn't
look
Post by Nicol Bolas
like a template suddenly became a template. Explain to me why I have to
implement it in a header, even though it looks exactly like every other
non-template function declaration/definition.
To the novice C++ programmer, it isn't "all just programming." Whether
something is a template matters.
Ah, the "won't somebody think of the children" argument.
The answer to why it suddenly became a template is that its parameter
is a concept, not a type. A concept is a family of types. I don't see
why that should be much harder to teach than "a function template is a
family of functions" and "a class template is a family of types".
If a "family of functions" is so fundamentally different from a regular
function that it can't be declared/defined in the same way, why does it
look exactly like a regular function? If swapping one identifier for
another can so radically change how you go about implementing something,
shouldn't it be more syntactically obvious that you've made a major change?

Without the template keyword, it doesn't look like a template. And
therefore, it is not immediately obvious that it should be treated as such.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Bjarne Stroustrup
2015-03-06 18:09:16 UTC
Permalink
Post by Nicol Bolas
Post by Nicol Bolas
Explain to me, the novice C++ programmer, why this thing which
doesn't look
Post by Nicol Bolas
like a template suddenly became a template. Explain to me why I
have to
Post by Nicol Bolas
implement it in a header, even though it looks exactly like
every other
Post by Nicol Bolas
non-template function declaration/definition.
To the novice C++ programmer, it isn't "all just programming."
Whether
Post by Nicol Bolas
something is a template matters.
Ah, the "won't somebody think of the children" argument.
The answer to why it suddenly became a template is that its parameter
is a concept, not a type. A concept is a family of types. I don't see
why that should be much harder to teach than "a function template is a
family of functions" and "a class template is a family of types".
If a "family of functions" is so fundamentally different from a
regular function that it can't be declared/defined in the same way,
why does it look exactly like a regular function? If swapping one
identifier for another can so radically change how you go about
implementing something, shouldn't it be more syntactically obvious
that you've made a major change?
Without the template keyword, it doesn't look like a template. And
therefore, it is not immediately obvious that it should be treated as such.
People will learn. Learning that
void f(auto);
implies template is kid's play compared to some things we expect people
to figure out.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
'Geoffrey Romer' via ISO C++ Standard - Discussion
2015-03-06 18:22:35 UTC
Permalink
Post by Nicol Bolas
Post by Jonathan Wakely
Post by Nicol Bolas
Explain to me, the novice C++ programmer, why this thing which doesn't
look
Post by Nicol Bolas
like a template suddenly became a template. Explain to me why I have to
implement it in a header, even though it looks exactly like every other
non-template function declaration/definition.
To the novice C++ programmer, it isn't "all just programming." Whether
something is a template matters.
Ah, the "won't somebody think of the children" argument.
The answer to why it suddenly became a template is that its parameter
is a concept, not a type. A concept is a family of types. I don't see
why that should be much harder to teach than "a function template is a
family of functions" and "a class template is a family of types".
If a "family of functions" is so fundamentally different from a regular
function that it can't be declared/defined in the same way, why does it
look exactly like a regular function? If swapping one identifier for
another can so radically change how you go about implementing something,
shouldn't it be more syntactically obvious that you've made a major change?
Without the template keyword, it doesn't look like a template. And
therefore, it is not immediately obvious that it should be treated as such.
People will learn. Learning that
void f(auto);
implies template is kid's play compared to some things we expect people to
figure out.
That's not the case he's talking about. He's talking about this one:

void f(T);

I don't see how "people will learn" to tell whether that's a template,
because there just fundamentally isn't enough information there to answer
that question, and in real code the necessary information might be anywhere
in the transitive #include graph.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Bjarne Stroustrup
2015-03-06 18:32:10 UTC
Permalink
On Fri, Mar 6, 2015 at 10:09 AM, Bjarne Stroustrup
Post by Nicol Bolas
Post by Nicol Bolas
Explain to me, the novice C++ programmer, why this thing
which doesn't look
Post by Nicol Bolas
like a template suddenly became a template. Explain to me
why I have to
Post by Nicol Bolas
implement it in a header, even though it looks exactly like
every other
Post by Nicol Bolas
non-template function declaration/definition.
To the novice C++ programmer, it isn't "all just
programming." Whether
Post by Nicol Bolas
something is a template matters.
Ah, the "won't somebody think of the children" argument.
The answer to why it suddenly became a template is that its parameter
is a concept, not a type. A concept is a family of types. I don't see
why that should be much harder to teach than "a function template is a
family of functions" and "a class template is a family of types".
If a "family of functions" is so fundamentally different from a
regular function that it can't be declared/defined in the same
way, why does it look exactly like a regular function? If
swapping one identifier for another can so radically change how
you go about implementing something, shouldn't it be more
syntactically obvious that you've made a major change?
Without the template keyword, it doesn't look like a template.
And therefore, it is not immediately obvious that it should be
treated as such.
People will learn. Learning that
void f(auto);
implies template is kid's play compared to some things we expect
people to figure out.
void f(T);
I don't see how "people will learn" to tell whether that's a template,
because there just fundamentally isn't enough information there to
answer that question, and in real code the necessary information might
be anywhere in the transitive #include graph.
Reminds me of people complaining that they don't know which type Foo is in

void f(Foo);

and therefore they don't know what arguments it insists.

That can indeed be a real problem, but not one that I loose sleep over.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Scott Prager
2015-03-06 19:36:56 UTC
Permalink
Post by Bjarne Stroustrup
Reminds me of people complaining that they don't know which type Foo is in
void f(Foo);
and therefore they don't know what arguments it insists.
That can indeed be a real problem, but not one that I loose sleep over.
Examples like this, whether *Foo* is a concept or concrete type, made me
consider that functions with concept arguments should be labeled as
templates... but then I realized the contradiction: If *Foo* is a type and
one
wants to call it, one must look up *Foo*'s declaration. Therefor, *Foo*
being a
concept doesn't actually require any more or less knowledge of the code base
than it being a type. In either case, the declaration must be looked up.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Nevin Liber
2015-03-06 18:42:14 UTC
Permalink
On 6 March 2015 at 12:22, 'Geoffrey Romer' via ISO C++ Standard -
Post by Faisal Vali
void f(T);
I don't see how "people will learn" to tell whether that's a template,
because there just fundamentally isn't enough information there to answer
that question, and in real code the necessary information might be anywhere
in the transitive #include graph.
There are two audiences (As Andrew pointed out in his reply to my previous
message):

1. The person calling the function. For the most part, they won't know or
care whether or not it is a template function; they just include the
correct header and call it.

2. The person defining the function. They have to know whether or not it
is a template or a specific concrete type, but they had to know that anyway
to write the function.
--
Nevin ":-)" Liber <mailto:***@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Tom Honermann
2015-03-06 19:04:08 UTC
Permalink
Post by Nevin Liber
There are two audiences (As Andrew pointed out in his reply to my
1. The person calling the function. For the most part, they won't know
or care whether or not it is a template function; they just include the
correct header and call it.
2. The person defining the function. They have to know whether or not
it is a template or a specific concrete type, but they had to know that
anyway to write the function.
I would argue for a third audience (though arguably a subset of the 2nd
case above):

3. The person modifying the function. They have to know whether or not
it is a template or a specific concrete type.

We can say that, if a person changes a function without first
determining that and causes a regression, well shame on them. I think
that is fair. But I think we can do better by offering a little assistance.

Tom.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Andrew Sutton
2015-03-06 19:11:29 UTC
Permalink
I would argue for a third audience (though arguably a subset of the 2nd case
3. The person modifying the function. They have to know whether or not it
is a template or a specific concrete type.
We can say that, if a person changes a function without first determining
that and causes a regression, well shame on them. I think that is fair.
But I think we can do better by offering a little assistance.
But do we have to mandate that assistance in every case?

Andrew
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Tom Honermann
2015-03-06 19:48:57 UTC
Permalink
Post by Andrew Sutton
I would argue for a third audience (though arguably a subset of the 2nd case
3. The person modifying the function. They have to know whether or not it
is a template or a specific concrete type.
We can say that, if a person changes a function without first determining
that and causes a regression, well shame on them. I think that is fair.
But I think we can do better by offering a little assistance.
But do we have to mandate that assistance in every case?
But do we have to obscure the nature of the function in any cases?

What advantage is gained by eliminating the need for a single 'template'
or other "this-is-a-template" identifier on the function declaration.
Saving keystrokes on a single token doesn't strike me as a big win.

Is your view that allowing template and non-template functions to share
a common declaration syntax makes C++ simpler? From my perspective, it
actually makes the language more difficult because it obscures
semantically relevant details.

Tom.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Tony Van Eerd
2015-03-06 18:58:20 UTC
Permalink
If all we need is auto, then is the next step:

struct X
{
int x;
auto y;
};

X is obviously a template?
So is Y:

struct Y
{
int x;
ForwardIterator y;
};

‎?

(Again, I'm not actually against 'auto means template function'‎; I just bring up counter arguments to be comfortable that we explored the design space and that we have a path of consistency going forward)

Tony


Sent from my BlackBerry 10 Turing machine.
From: Bjarne Stroustrup
Sent: Friday, March 6, 2015 1:14 PM
To: c++std-***@accu.org; std-***@isocpp.org
Reply To: c++std-***@accu.org
Cc: std-***@isocpp.org; ***@gmail.com; ***@microsoft.com
Subject: [c++std-core-27227] Re: An implementation of enhanced auto deduction and abbreviated template syntax using Clang
Post by Nicol Bolas
Explain to me, the novice C++ programmer, why this thing which doesn't look
like a template suddenly became a template. Explain to me why I have to
implement it in a header, even though it looks exactly like every other
non-template function declaration/definition.
To the novice C++ programmer, it isn't "all just programming." Whether
something is a template matters.
Ah, the "won't somebody think of the children" argument.

The answer to why it suddenly became a template is that its parameter
is a concept, not a type. A concept is a family of types. I don't see
why that should be much harder to teach than "a function template is a
family of functions" and "a class template is a family of types".

If a "family of functions" is so fundamentally different from a regular function that it can't be declared/defined in the same way, why does it look exactly like a regular function? If swapping one identifier for another can so radically change how you go about implementing something, shouldn't it be more syntactically obvious that you've made a major change?

Without the template keyword, it doesn't look like a template. And therefore, it is not immediately obvious that it should be treated as such.


People will learn. Learning that
void f(auto);
implies template is kid's play compared to some things we expect people to figure out.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Andrew Sutton
2015-03-06 19:09:07 UTC
Permalink
Post by Tony Van Eerd
struct X
{
int x;
auto y;
};
Ermm... yikes, no. That's like saying that this is a template

void f()
{
auto x = y;
}

because it has an auto.

I seem to recall some EWG papers or discussion about using auto as the type
of a member variable. I don't remember what the outcome was.

(Again, I'm not actually against 'auto means template function'‎; I just
Post by Tony Van Eerd
bring up counter arguments to be comfortable that we explored the design
space and that we have a path of consistency going forward)
I remember discussing these questions in Bjarne's office years ago... We
have explored in this direction, and here be dragons.

Andrew
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Faisal Vali
2015-03-06 19:29:52 UTC
Permalink
[dropping core]
Post by Andrew Sutton
Post by Tony Van Eerd
struct X
{
int x;
auto y;
};
Ermm... yikes, no. That's like saying that this is a template
void f()
{
auto x = y;
}
because it has an auto.
I seem to recall some EWG papers or discussion about using auto as the type
of a member variable. I don't remember what the outcome was.
http://www2.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3897.html
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Matthew Fioravante
2015-03-06 19:14:45 UTC
Permalink
Post by Tony Van Eerd
struct X
{
int x;
auto y;
};
X is obviously a template
Lets have even more fun:

//This is a template
struct A {
auto x;
};

//This is not a template
struct B {
auto x = 1;
};


(for the record, I'd be happy either way but its good to play devils
advocate)
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Andrew Sutton
2015-03-06 19:24:21 UTC
Permalink
Post by Matthew Fioravante
//This is a template
struct A {
auto x;
};
No, it's not. Something in the declaration shouldn't change the nature
of its declaration (apparently except deduced return types). And here's why:

struct A; // Is this a template? Clearly not

struct A {
auto x; // Makes A a template?
};

That's just insane.

Andrew
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Scott Prager
2015-03-06 19:28:44 UTC
Permalink
Post by Matthew Fioravante
Post by Tony Van Eerd
struct X
{
int x;
auto y;
};
X is obviously a template
//This is a template
struct A {
auto x;
};
//This is not a template
struct B {
auto x = 1;
};
(for the record, I'd be happy either way but its good to play devils
advocate)
These examples seem rather farcical to me. How would we instantiate such a
type? At least with functions, we get implicit specialization based on the
arguments supplied, but with types... to make it feasible, we'd have to
enable
this syntax:

std::pair p{x, std::ref(y)}; // std::pair<X, Y&>

...and I don't see that happening. I think the analogy of template classes
to
template functions is apples to oranges since they operate by very different
rules.

*(Not that I don't think the above syntax would be great, just not as
feasible.)*
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Vicente J. Botet Escriba
2015-03-07 16:51:07 UTC
Permalink
Post by Tony Van Eerd
struct X
{
int x;
auto y;
};
X is obviously a template?
struct Y
{
int x;
ForwardIterator y;
};
‎?
(Again, I'm not actually against 'auto means template function'‎; I
just bring up counter arguments to be comfortable that we explored the
design space and that we have a path of consistency going forward)
While for template functions the type is deduced, how could you deduce
the type for auto or ForwardIterator. How would you declare an instance
of X, or a parameter of type X.

X<???> v;

what if we had

struct X
{
auto x;
auto y;
};

X<???, ???> v;

Should the parameters need to be given in the order of declaration of
the auto/Concept data members?

I find this confusing.

Vicente
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Jonathan Wakely
2015-03-07 17:20:23 UTC
Permalink
This wild speculation seems off-topic on c++std-core, can it be
continued just at std-discussion and/or std-proposals?
Post by Tony Van Eerd
struct X
{
int x;
auto y;
};
X is obviously a template?
struct Y
{
int x;
ForwardIterator y;
};
‎?
(Again, I'm not actually against 'auto means template function'‎; I just
bring up counter arguments to be comfortable that we explored the design
space and that we have a path of consistency going forward)
While for template functions the type is deduced, how could you deduce the
type for auto or ForwardIterator. How would you declare an instance of X, or
a parameter of type X.
X<???> v;
what if we had
struct X
{
auto x;
auto y;
};
X<???, ???> v;
Should the parameters need to be given in the order of declaration of the
auto/Concept data members?
I find this confusing.
Vicente
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
David Rodríguez Ibeas
2015-03-07 21:17:54 UTC
Permalink
When I went over the concepts paper there were a couple of things that
troubled me a bit (not a lot) and that are relevant to this discussion.
The first one is that the syntax does not call out that the identifier
names a concept. This is also the case in C++14, C++11 and C++03, so
nothing new, just adding one more dimension (before, a new type could be
added that changed the meaning of an identifier), but with concepts and a
non-distinguishible syntax now we have more interactions.

The second thing that concerned me is the variety of syntaxes to represent
constrained templates. This is driven by two conflicting goals: terseness
and expressive power. In addition to that, I disliked the fact that the
use of a place-holder type has different semantics: 'void f(auto x, auto
y)' introduces two unrelated types for a and b, while 'void f(concept a,
concept b)' introduces a single type for both a and b.

An alternative syntax that came to mind, was to use the syntax for the
template introduction as a placeholder: 'void f(concept{T} x, concept{U}
y)' would introduce two types T and U, both satisfying the 'concept' after
the introduction of the type with 'concept{T}', the identifier T could be
reused to represent the same type for different parameters: 'void
f(concept{T} x, T y)' [equivalent to the Concepts TS: 'void f(concept x,
concept y)'. Compared with the previous syntax, there is a bit of
overhead, but I don't consider that to be a *lot* of overhead. Another
advantage of this syntax is that in a concise form you can allow for
multiple arguments to have different types satisfying the same concept:
'bool equal(FwdIter{It1} first, It1 last, FwdIter{It2} first2, It2
last2)'. This is currently not allowed in the concepts TS with the more
concise syntax.

As far as I know, this syntax is illegal in the language at this point, so
it is clearly identifiable as relating to a concept, and could even be used
to drive lookup to ignore types when searching for the identifier
'concept'. The same syntax could be allowed (not required) for the auto
placeholder to enable an unconstrained template in which two arguments are
of the same type: void f(auto{T} x, T y).

Similar to the template introduction case, it would be possible to use the
syntax to introduce multiple types at once: 'bool equal(Comparable{T,U}
const & x, U const & y) { return x == y; }' If this is allowed, there would
not be a need to have the template introduction syntax. This is really the
same thing, except that it would not appear outside of the argument list,
but inlined with the parameters, which makes it a valid alternative for
lambas [](Comparable{T,U} const & x, U const & y) { return x == y; }.

Whether this is the good solution or something else is, I'd like to have
less alternative syntaxes, and I am willing to pay a bit on terseness (this
is not a huge difference) for clarity, reducing the alternatives and
flexibility.

David

* An open question, for which I don't have a good answer is whether the
syntax should be composable: bool f(concept1{concept2{T}, concept3{U}} t, U
u) meaning:

template <typename T, typename U>
requires concept2<T> and concept3<U> and concept1<T,U> // pseudo code, not
sure if this is valid syntax
bool f(T t, U u);

* One thing that bothers me of this syntax (but that is also a problem in
the template introduction one) is whether all identifiers inside the {}
create new template parameters or if we can find a way of referring to
identifiers in the scope of the declaration:

void f(auto{T} t) {
[=t](Comparable{U,T} x) { return u == t; } // 1
}

Is there a possible concise syntax that unambiguously allows us to state
that 'T' is not a type introduced by 'Comparable{U,T}'? I have considered
some alternatives but I am not too fond of any of them, the one that seems
lighter would be abusing additional curlies:

Comparable{T, {U}} t // This introduces a new type T, but looks up U in the
current scope, requires Comparable<T,U>, decltype(t) == T
Comparable{{T}, U} u // This introduces a new type U, but looks up T in the
current scope, requires Comparable<T,U>, decltype(u) == U (i.e. the syntax
'concept{x,y,z}' is equivalent to introducing the unescaped (by lack of a
better name) types as template arguments and the subsitution of the
placeholder for the first such introduced type.
Post by Jonathan Wakely
This wild speculation seems off-topic on c++std-core, can it be
continued just at std-discussion and/or std-proposals?
Post by Tony Van Eerd
struct X
{
int x;
auto y;
};
X is obviously a template?
struct Y
{
int x;
ForwardIterator y;
};
‎?
(Again, I'm not actually against 'auto means template function'‎; I just
bring up counter arguments to be comfortable that we explored the design
space and that we have a path of consistency going forward)
While for template functions the type is deduced, how could you deduce
the
Post by Tony Van Eerd
type for auto or ForwardIterator. How would you declare an instance of
X, or
Post by Tony Van Eerd
a parameter of type X.
X<???> v;
what if we had
struct X
{
auto x;
auto y;
};
X<???, ???> v;
Should the parameters need to be given in the order of declaration of the
auto/Concept data members?
I find this confusing.
Vicente
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Bjarne Stroustrup
2015-03-07 21:55:47 UTC
Permalink
If someone has a proposal for changes to the concepts TS, I suggest they
write a paper for the evolution group to consider.

We have discussed "auto" and concepts for years (I first described "void
f(auto);" to the EWG in 2004 or so) and I have seen little new or in
terms of facilities or technical arguments in this long thread.
Post by David Rodríguez Ibeas
When I went over the concepts paper there were a couple of things that
troubled me a bit (not a lot) and that are relevant to this
discussion. The first one is that the syntax does not call out that
the identifier names a concept. This is also the case in C++14, C++11
and C++03, so nothing new, just adding one more dimension (before, a
new type could be added that changed the meaning of an identifier),
but with concepts and a non-distinguishible syntax now we have more
interactions.
The second thing that concerned me is the variety of syntaxes to
represent constrained templates. This is driven by two conflicting
goals: terseness and expressive power. In addition to that, I
disliked the fact that the use of a place-holder type has different
semantics: 'void f(auto x, auto y)' introduces two unrelated types for
a and b, while 'void f(concept a, concept b)' introduces a single type
for both a and b.
An alternative syntax that came to mind, was to use the syntax for the
template introduction as a placeholder: 'void f(concept{T} x,
concept{U} y)' would introduce two types T and U, both satisfying the
'concept' after the introduction of the type with 'concept{T}', the
identifier T could be reused to represent the same type for different
parameters: 'void f(concept{T} x, T y)' [equivalent to the Concepts
TS: 'void f(concept x, concept y)'. Compared with the previous
syntax, there is a bit of overhead, but I don't consider that to be a
*lot* of overhead. Another advantage of this syntax is that in a
concise form you can allow for multiple arguments to have different
types satisfying the same concept: 'bool equal(FwdIter{It1} first, It1
last, FwdIter{It2} first2, It2 last2)'. This is currently not allowed
in the concepts TS with the more concise syntax.
As far as I know, this syntax is illegal in the language at this
point, so it is clearly identifiable as relating to a concept, and
could even be used to drive lookup to ignore types when searching for
the identifier 'concept'. The same syntax could be allowed (not
required) for the auto placeholder to enable an unconstrained template
in which two arguments are of the same type: void f(auto{T} x, T y).
Similar to the template introduction case, it would be possible to use
the syntax to introduce multiple types at once: 'bool
equal(Comparable{T,U} const & x, U const & y) { return x == y; }' If
this is allowed, there would not be a need to have the template
introduction syntax. This is really the same thing, except that it
would not appear outside of the argument list, but inlined with the
parameters, which makes it a valid alternative for lambas
[](Comparable{T,U} const & x, U const & y) { return x == y; }.
Whether this is the good solution or something else is, I'd like to
have less alternative syntaxes, and I am willing to pay a bit on
terseness (this is not a huge difference) for clarity, reducing the
alternatives and flexibility.
David
* An open question, for which I don't have a good answer is whether
the syntax should be composable: bool f(concept1{concept2{T},
template <typename T, typename U>
requires concept2<T> and concept3<U> and concept1<T,U> // pseudo code,
not sure if this is valid syntax
bool f(T t, U u);
* One thing that bothers me of this syntax (but that is also a problem
in the template introduction one) is whether all identifiers inside
the {} create new template parameters or if we can find a way of
void f(auto{T} t) {
[=t](Comparable{U,T} x) { return u == t; } // 1
}
Is there a possible concise syntax that unambiguously allows us to
state that 'T' is not a type introduced by 'Comparable{U,T}'? I have
considered some alternatives but I am not too fond of any of them, the
Comparable{T, {U}} t // This introduces a new type T, but looks up U
in the current scope, requires Comparable<T,U>, decltype(t) == T
Comparable{{T}, U} u // This introduces a new type U, but looks up T
in the current scope, requires Comparable<T,U>, decltype(u) == U (i.e.
the syntax 'concept{x,y,z}' is equivalent to introducing the unescaped
(by lack of a better name) types as template arguments and the
subsitution of the placeholder for the first such introduced type.
This wild speculation seems off-topic on c++std-core, can it be
continued just at std-discussion and/or std-proposals?
Post by Tony Van Eerd
struct X
{
int x;
auto y;
};
X is obviously a template?
struct Y
{
int x;
ForwardIterator y;
};
‎?
(Again, I'm not actually against 'auto means template
function'‎; I just
Post by Tony Van Eerd
bring up counter arguments to be comfortable that we explored
the design
Post by Tony Van Eerd
space and that we have a path of consistency going forward)
While for template functions the type is deduced, how could you
deduce the
Post by Tony Van Eerd
type for auto or ForwardIterator. How would you declare an
instance of X, or
Post by Tony Van Eerd
a parameter of type X.
X<???> v;
what if we had
struct X
{
auto x;
auto y;
};
X<???, ???> v;
Should the parameters need to be given in the order of
declaration of the
Post by Tony Van Eerd
auto/Concept data members?
I find this confusing.
Vicente
--
---
You received this message because you are subscribed to the Google
Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it,
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Tony Van Eerd
2015-03-07 22:18:20 UTC
Permalink
For the in-scope case, did you consider :U which is similar to ::U (which would be U in the global scope)?


Sent from my BlackBerry 10 Turing machine.
From: David Rodríguez Ibeas
Sent: Saturday, March 7, 2015 4:21 PM
To: std-***@isocpp.org
Reply To: c++std-***@accu.org
Cc: c++std-core; std-***@isocpp.org; ***@gmail.com; ***@microsoft.com
Subject: [c++std-core-27261] Re: [std-discussion] Re: Re: An implementation of enhanced auto deduction and abbreviated template syntax using Clang


When I went over the concepts paper there were a couple of things that troubled me a bit (not a lot) and that are relevant to this discussion. The first one is that the syntax does not call out that the identifier names a concept. This is also the case in C++14, C++11 and C++03, so nothing new, just adding one more dimension (before, a new type could be added that changed the meaning of an identifier), but with concepts and a non-distinguishible syntax now we have more interactions.

The second thing that concerned me is the variety of syntaxes to represent constrained templates. This is driven by two conflicting goals: terseness and expressive power. In addition to that, I disliked the fact that the use of a place-holder type has different semantics: 'void f(auto x, auto y)' introduces two unrelated types for a and b, while 'void f(concept a, concept b)' introduces a single type for both a and b.

An alternative syntax that came to mind, was to use the syntax for the template introduction as a placeholder: 'void f(concept{T} x, concept{U} y)' would introduce two types T and U, both satisfying the 'concept' after the introduction of the type with 'concept{T}', the identifier T could be reused to represent the same type for different parameters: 'void f(concept{T} x, T y)' [equivalent to the Concepts TS: 'void f(concept x, concept y)'. Compared with the previous syntax, there is a bit of overhead, but I don't consider that to be a *lot* of overhead. Another advantage of this syntax is that in a concise form you can allow for multiple arguments to have different types satisfying the same concept: 'bool equal(FwdIter{It1} first, It1 last, FwdIter{It2} first2, It2 last2)'. This is currently not allowed in the concepts TS with the more concise syntax.

As far as I know, this syntax is illegal in the language at this point, so it is clearly identifiable as relating to a concept, and could even be used to drive lookup to ignore types when searching for the identifier 'concept'. The same syntax could be allowed (not required) for the auto placeholder to enable an unconstrained template in which two arguments are of the same type: void f(auto{T} x, T y).

Similar to the template introduction case, it would be possible to use the syntax to introduce multiple types at once: 'bool equal(Comparable{T,U} const & x, U const & y) { return x == y; }' If this is allowed, there would not be a need to have the template introduction syntax. This is really the same thing, except that it would not appear outside of the argument list, but inlined with the parameters, which makes it a valid alternative for lambas [](Comparable{T,U} const & x, U const & y) { return x == y; }.

Whether this is the good solution or something else is, I'd like to have less alternative syntaxes, and I am willing to pay a bit on terseness (this is not a huge difference) for clarity, reducing the alternatives and flexibility.

David

* An open question, for which I don't have a good answer is whether the syntax should be composable: bool f(concept1{concept2{T}, concept3{U}} t, U u) meaning:

template <typename T, typename U>
requires concept2<T> and concept3<U> and concept1<T,U> // pseudo code, not sure if this is valid syntax
bool f(T t, U u);

* One thing that bothers me of this syntax (but that is also a problem in the template introduction one) is whether all identifiers inside the {} create new template parameters or if we can find a way of referring to identifiers in the scope of the declaration:

void f(auto{T} t) {
[=t](Comparable{U,T} x) { return u == t; } // 1
}

Is there a possible concise syntax that unambiguously allows us to state that 'T' is not a type introduced by 'Comparable{U,T}'? I have considered some alternatives but I am not too fond of any of them, the one that seems lighter would be abusing additional curlies:

Comparable{T, {U}} t // This introduces a new type T, but looks up U in the current scope, requires Comparable<T,U>, decltype(t) == T
Comparable{{T}, U} u // This introduces a new type U, but looks up T in the current scope, requires Comparable<T,U>, decltype(u) == U (i.e. the syntax 'concept{x,y,z}' is equivalent to introducing the unescaped (by lack of a better name) types as template arguments and the subsitution of the placeholder for the first such introduced type.

On Sat, Mar 7, 2015 at 12:20 PM, Jonathan Wakely <***@kayari.org<mailto:***@kayari.org>> wrote:
This wild speculation seems off-topic on c++std-core, can it be
continued just at std-discussion and/or std-proposals?
Post by Tony Van Eerd
struct X
{
int x;
auto y;
};
X is obviously a template?
struct Y
{
int x;
ForwardIterator y;
};
‎?
(Again, I'm not actually against 'auto means template function'‎; I just
bring up counter arguments to be comfortable that we explored the design
space and that we have a path of consistency going forward)
While for template functions the type is deduced, how could you deduce the
type for auto or ForwardIterator. How would you declare an instance of X, or
a parameter of type X.
X<???> v;
what if we had
struct X
{
auto x;
auto y;
};
X<???, ???> v;
Should the parameters need to be given in the order of declaration of the
auto/Concept data members?
I find this confusing.
Vicente
--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org<mailto:std-discussion%***@isocpp.org>.
To post to this group, send email to std-***@isocpp.org<mailto:std-***@isocpp.org>.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Tom Honermann
2015-03-06 17:46:30 UTC
Permalink
Oh, you could say, "well just put /everything/ in a header." That's...
insane.
and would cause link errors unless also specified as inline. Now the
novice learns to define all their functions as inline functions in a header.

I'm not sure I really buy the novice argument though. I learned this,
others can too.

The real issue to me is that the abbreviated syntax does not permit me
to syntactically determine if a function definition is a template or not
- semantic information is required (unless at least one of the
placeholder types is 'auto').

I don't see modules helping with that.

Tom.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Nicol Bolas
2015-03-06 18:01:35 UTC
Permalink
Post by Tom Honermann
Oh, you could say, "well just put /everything/ in a header." That's...
insane.
and would cause link errors unless also specified as inline. Now the
novice learns to define all their functions as inline functions in a header.
I'm not sure I really buy the novice argument though. I learned this,
others can too.
The real issue to me is that the abbreviated syntax does not permit me
to syntactically determine if a function definition is a template or not
- semantic information is required (unless at least one of the
placeholder types is 'auto').
I don't see modules helping with that.
The question there is why you need to "syntactically determine if a
function definition is a template or not"? Why do you care? If the
compile-time difference is negligible, and you don't need to get a function
pointer to it, why would you need to know whether it's a template or not?
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Tom Honermann
2015-03-06 19:26:19 UTC
Permalink
Post by Nicol Bolas
The question there is why you need to "syntactically determine if a
function definition is a template or not"? Why do you care? If the
compile-time difference is negligible, and you don't need to get a
function pointer to it, why would you need to know whether it's a
template or not?
Because this:

void f(X&& x) {}

may be called with an rvalue or lvalue argument if X is a concept, but
may only be called with an rvalue if X is a type. That may be important
to a library interface.

And because this:

void f(X x) {
static int invoke_count;
++invoke_count;
}

will maintain a count of either every invocation of f() or every
invocation of an instantiation of f() depending on whether X is a
concept or not.

And because this:

void f(X x) {}

may be moved from a primary source file to a header if X is a concept,
but not if X is a type.

And because this:

void f(X x) {
X::type t;
}

will require 'typename' if X is a concept, but will not allow it if X is
not (of course, the compiler will be happy to tell me about this one).

Why do I care about the above? Because, in a large code base that I'm
not familiar with, having to go find out what X is detracts from getting
the work done.

Tom.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Herb Sutter
2015-03-06 18:27:23 UTC
Permalink
To the novice C++ programmer, it isn't "all just programming." Whether something is a template matters.
Why? Only because of where you put the definition, and that’s (a) teachable and (b) not new because the same issue exists already with:

auto f() { 
 };

This is not a template, but must appear in a header. This is amazingly similar – and easy to teach as “if the declaration mentions ‘auto’ or a concept name, the compiler needs the definition, either to deduce something or to inline the body into the caller.” Right?

Herb

PS – Since you mention “novices” writing templates, in my experience (and to my surprise) I’ve found that not only novices but also intermediate developers (like 5-7 year veterans) don’t write templates very much. [I expect this to change with concepts, for the good.] I discovered this by chance when I had a class exercise that included writing a very simple template, and as I walked through the class during the exercise I was surprised that most of the groups asked about the syntax for writing a template – a dead giveaway that they didn’t write templates very often, yet these were pretty experienced developers who used C++ every day, but just never needed to write templates much in their normal code. To validate that this wasn’t just an outlier group, I’ve watched that exercise in a number of classes over several years and found a similar result – the majority of even reasonably experienced C++ programmers asked about the syntax for how to write a template.



From: Nicol Bolas [mailto:***@gmail.com]
Sent: Friday, March 6, 2015 9:21 AM
To: std-***@isocpp.org
Cc: c++std-***@accu.org; std-***@isocpp.org; ***@gmail.com; Herb Sutter
Subject: Re: [c++std-core-27204] Re: An implementation of enhanced auto deduction and abbreviated template syntax using Clang

On Thursday, March 5, 2015 at 7:24:32 PM UTC-5, Herb Sutter wrote:
To paraphrase Stroustrup, it’s not about functional programming and object-oriented programming and generic programming
 “it’s all just programming.”
Templates are a fundamentally different kind of construct
Why? Every full specialization of a function template is just a function.

OK, let's explore this.

Let's say that I'm a novice C++ programmer. I don't really know much about the language. But I have some basic knowledge.

Now, I've been told that when I write functions, I put a prototype in a header file so that other people can use it. But I also put the implementation in a source file, so that it stays hidden. So I write:
//header
RetType func_name(Type1 arg1, ...);

//source
RetType func_name(Type1 arg1, ...)
{
//implementation
}


OK, fine.

I've also been told about a different class of functions: template functions. For reasons I haven't been told and don't much care about (since I'm a novice), I have to put the implementation in the header file. So I know that if I type the word "template", then that function's implementation has to go into a header. So I always do this:
//header
template<typename T>
RetType func_name_template(T arg1, ...)
{
//implementation
}

//source doesn't exist.


OK, fine. So... explain to me, the novice C++ programmer, why this doesn't work:
//header
RetType func_name_concept(ConceptName arg1, ...);

//source
RetType func_name_concept(ConceptName arg1, ...)
{
//implementation
}

Explain to me, the novice C++ programmer, why this thing which doesn't look like a template suddenly became a template. Explain to me why I have to implement it in a header, even though it looks exactly like every other non-template function declaration/definition.

To the novice C++ programmer, it isn't "all just programming." Whether something is a template matters.

Oh, you could say, "well just put everything in a header." That's... insane. Compile times for C++ projects of significant size are already huge even when you try to only put what you need in headers. Adding the burden of shoving everything in a header is crazy.

Now, if you can promise me that the same version of C++ that will include this terse syntax will also include modules, I will immediately stop caring. Once that exists, then most of the differences between template and non-template functions will be erased. And therefore, so too can the syntactic differences.

But so long as there is a difference in how you implement template and non-template functions, I say that there should be an obvious difference in syntax too.
My issue is with, well, any syntax that declares a template without having to type either the word "template" or the use of "<>" brackets.
That ship has sailed:

auto plus = [](auto x, auto y) { return x+y; }

which even already decays to an ordinary pointer to function, etc.

That doesn't decay into a function pointer. It can't; the operator() is a template.


Clarifying Q: Are we mainly arguing about whether to require the three characters =, [, and ] ?
Except that there is a difference between creating a lambda (which creates a functor) and creating a function (which can be overloaded).

Not only has the ship sailed, but I for one like the direction it’s sailing. I see no reason why functions should be forced to spell “template” and “<>”. What value does it add? It’s “just programming.” In fact, if we didn’t have backward compatibility issues with unnamed parameters and such, I’d personally probably be fine with just “auto plus(x,y){x+y}” as an equivalent function definition. That still doesn’t lose any information.

Gratuitous syntax is often unnecessary and usually harmful. Saying

template<class T, class U>
auto(T x, U y) -> decltype(x+y) { return x+y; }

does not appear to me to contain any more information than

auto plus(auto x, auto y) { return x+y; }

does it?
If you take out the late specified return type (I specifically said that static deduction was fine), then I don't see the problem with the first one.


Requiring the verbose syntax is gratuitous, if the verbose syntax does not add information, does not serve to disambiguate anything, and does not highlight a dangerous operation or anything else I can see that deserves to have attention called to it.

There’s a disturbing (to me and at least some others) trend in C++ these days: People seem to be very prone to wanting “more syntax” lately. It’s rather Vasa-like, if only lexically. Let me channel certain influential committee members and say: ‘People these days are always asking for more syntax! There’s no proposal they’ve seen that they couldn’t make uglier with more syntax!’

Important note: The point here is NOT terseness for terseness’ sake. I am not arguing that terser is somehow better, that terseness is virtuous in itself. Too many people glorify languages because they’re terser; fewer characters alone doesn’t make code clearer. Rather, my point is to avoid gratuitous verbosity. At the other end of the pendulum, too many people glorify verbose syntax because they think _that_ is somehow inherently clearer; usually it isn’t. So I am arguing that neither is verbosity virtuous in itself.

Herb
The virtue to me of the large syntax of templates is this:

Templates have to be treated differently from non-templates. They have different needs of where their implementations live. And because of those needs, templates make your code compile slower. Even ignoring the compile-time cost of template instantiation, your source has to go in the header. And if that header is included in more than one place, then the source for that template must be recompiled for every place it is included.

Therefore, the bulky template syntax pokes you in the eye every time you write something that's going to compile slower. It immediately lets you know that this function operates under fundamentally different rules than regular functions.

Again, if you could guarantee that we get modules alongside this syntax, I'd be fine, since using templates will not hurt your compile times nearly as much.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
John Spicer
2015-03-06 18:37:32 UTC
Permalink
Post by Herb Sutter
To the novice C++ programmer, it isn't "all just programming." Whether something is a template matters.
auto f() { 
 };
This is not a template, but must appear in a header. This is amazingly similar – and easy to teach as “if the declaration mentions ‘auto’ or a concept name, the compiler needs the definition, either to deduce something or to inline the body into the caller.” Right?
Actually, that is not right -- in fact, it is mostly wrong.

Only if the return type is deduced do you need a definition.

So:

void f(auto,auto);
void g(ForwardIterator);

do not need definitions.

John.
Post by Herb Sutter
Herb
PS – Since you mention “novices” writing templates, in my experience (and to my surprise) I’ve found that not only novices but also intermediate developers (like 5-7 year veterans) don’t write templates very much. [I expect this to change with concepts, for the good.] I discovered this by chance when I had a class exercise that included writing a very simple template, and as I walked through the class during the exercise I was surprised that most of the groups asked about the syntax for writing a template – a dead giveaway that they didn’t write templates very often, yet these were pretty experienced developers who used C++ every day, but just never needed to write templates much in their normal code. To validate that this wasn’t just an outlier group, I’ve watched that exercise in a number of classes over several years and found a similar result – the majority of even reasonably experienced C++ programmers asked about the syntax for how to write a template.
Sent: Friday, March 6, 2015 9:21 AM
Subject: Re: [c++std-core-27204] Re: An implementation of enhanced auto deduction and abbreviated template syntax using Clang
To paraphrase Stroustrup, it’s not about functional programming and object-oriented programming and generic programming
 “it’s all just programming.”
Templates are a fundamentally different kind of construct
Why? Every full specialization of a function template is just a function.
OK, let's explore this.
Let's say that I'm a novice C++ programmer. I don't really know much about the language. But I have some basic knowledge.
//header
RetType func_name(Type1 arg1, ...);
//source
RetType func_name(Type1 arg1, ...)
{
//implementation
}
OK, fine.
//header
template<typename T>
RetType func_name_template(T arg1, ...)
{
//implementation
}
//source doesn't exist.
//header
RetType func_name_concept(ConceptName arg1, ...);
//source
RetType func_name_concept(ConceptName arg1, ...)
{
//implementation
}
Explain to me, the novice C++ programmer, why this thing which doesn't look like a template suddenly became a template. Explain to me why I have to implement it in a header, even though it looks exactly like every other non-template function declaration/definition.
To the novice C++ programmer, it isn't "all just programming." Whether something is a template matters.
Oh, you could say, "well just put everything in a header." That's... insane. Compile times for C++ projects of significant size are already huge even when you try to only put what you need in headers. Adding the burden of shoving everything in a header is crazy.
Now, if you can promise me that the same version of C++ that will include this terse syntax will also include modules, I will immediately stop caring. Once that exists, then most of the differences between template and non-template functions will be erased. And therefore, so too can the syntactic differences.
But so long as there is a difference in how you implement template and non-template functions, I say that there should be an obvious difference in syntax too.
My issue is with, well, any syntax that declares a template without having to type either the word "template" or the use of "<>" brackets.
auto plus = [](auto x, auto y) { return x+y; }
which even already decays to an ordinary pointer to function, etc.
That doesn't decay into a function pointer. It can't; the operator() is a template.
Clarifying Q: Are we mainly arguing about whether to require the three characters =, [, and ] ?
Except that there is a difference between creating a lambda (which creates a functor) and creating a function (which can be overloaded).
Not only has the ship sailed, but I for one like the direction it’s sailing. I see no reason why functions should be forced to spell “template” and “<>”. What value does it add? It’s “just programming.” In fact, if we didn’t have backward compatibility issues with unnamed parameters and such, I’d personally probably be fine with just “auto plus(x,y){x+y}” as an equivalent function definition. That still doesn’t lose any information.
Gratuitous syntax is often unnecessary and usually harmful. Saying
template<class T, class U>
auto(T x, U y) -> decltype(x+y) { return x+y; }
does not appear to me to contain any more information than
auto plus(auto x, auto y) { return x+y; }
does it?
If you take out the late specified return type (I specifically said that static deduction was fine), then I don't see the problem with the first one.
Requiring the verbose syntax is gratuitous, if the verbose syntax does not add information, does not serve to disambiguate anything, and does not highlight a dangerous operation or anything else I can see that deserves to have attention called to it.
There’s a disturbing (to me and at least some others) trend in C++ these days: People seem to be very prone to wanting “more syntax” lately. It’s rather Vasa-like, if only lexically. Let me channel certain influential committee members and say: ‘People these days are always asking for more syntax! There’s no proposal they’ve seen that they couldn’t make uglier with more syntax!’
Important note: The point here is NOT terseness for terseness’ sake. I am not arguing that terser is somehow better, that terseness is virtuous in itself. Too many people glorify languages because they’re terser; fewer characters alone doesn’t make code clearer. Rather, my point is to avoid gratuitous verbosity. At the other end of the pendulum, too many people glorify verbose syntax because they think _that_ is somehow inherently clearer; usually it isn’t. So I am arguing that neither is verbosity virtuous in itself.
Herb
Templates have to be treated differently from non-templates. They have different needs of where their implementations live. And because of those needs, templates make your code compile slower. Even ignoring the compile-time cost of template instantiation, your source has to go in the header. And if that header is included in more than one place, then the source for that template must be recompiled for every place it is included.
Therefore, the bulky template syntax pokes you in the eye every time you write something that's going to compile slower. It immediately lets you know that this function operates under fundamentally different rules than regular functions.
Again, if you could guarantee that we get modules alongside this syntax, I'd be fine, since using templates will not hurt your compile times nearly as much.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Herb Sutter
2015-03-06 20:53:57 UTC
Permalink
This surprised me so I asked John offline what he meant, and I think we're not in disagreement. You can't call those unless there are (also) definitions.

What I said is correct: If auto (or a concept name) is used in the return type or parameter type, the definition must be available "in a header." And this is already true for auto return types.

I did not mean to imply that you couldn't also have a forward declaration too (which you can have for function templates but not for auto returns), but it still must be accompanied by a definition which was the point under discussion, namely that the definition still has to be available in the header.

Note that I'm excluding the "extern template" case, which is a special case and about controlling where instantiations occur (or limiting them) rather than about writing the generally usable function template itself... so IMO extern templates aren't applicable to this question.

Herb


From: John Spicer [mailto:***@edg.com]
Sent: Friday, March 6, 2015 10:38 AM
To: c++std-***@accu.org
Cc: Nicol Bolas; std-***@isocpp.org; std-***@isocpp.org; ***@gmail.com
Subject: [c++std-core-27231] Re: An implementation of enhanced auto deduction and abbreviated template syntax using Clang
To the novice C++ programmer, it isn't "all just programming." Whether something is a template matters.
Why? Only because of where you put the definition, and that's (a) teachable and (b) not new because the same issue exists already with:

auto f() { ... };

This is not a template, but must appear in a header. This is amazingly similar - and easy to teach as "if the declaration mentions 'auto' or a concept name, the compiler needs the definition, either to deduce something or to inline the body into the caller." Right?

Actually, that is not right -- in fact, it is mostly wrong.

Only if the return type is deduced do you need a definition.

So:

void f(auto,auto);
void g(ForwardIterator);

do not need definitions.

John.



Herb

PS - Since you mention "novices" writing templates, in my experience (and to my surprise) I've found that not only novices but also intermediate developers (like 5-7 year veterans) don't write templates very much. [I expect this to change with concepts, for the good.] I discovered this by chance when I had a class exercise that included writing a very simple template, and as I walked through the class during the exercise I was surprised that most of the groups asked about the syntax for writing a template - a dead giveaway that they didn't write templates very often, yet these were pretty experienced developers who used C++ every day, but just never needed to write templates much in their normal code. To validate that this wasn't just an outlier group, I've watched that exercise in a number of classes over several years and found a similar result - the majority of even reasonably experienced C++ programmers asked about the syntax for how to write a template.



From: Nicol Bolas [mailto:***@gmail.com<http://gmail.com>]
Sent: Friday, March 6, 2015 9:21 AM
To: std-***@isocpp.org<mailto:std-***@isocpp.org>
Cc: c++std-***@accu.org<mailto:c++std-***@accu.org>; std-***@isocpp.org<mailto:std-***@isocpp.org>; ***@gmail.com<mailto:***@gmail.com>; Herb Sutter
Subject: Re: [c++std-core-27204] Re: An implementation of enhanced auto deduction and abbreviated template syntax using Clang

On Thursday, March 5, 2015 at 7:24:32 PM UTC-5, Herb Sutter wrote:
To paraphrase Stroustrup, it's not about functional programming and object-oriented programming and generic programming... "it's all just programming."
Templates are a fundamentally different kind of construct
Why? Every full specialization of a function template is just a function.

OK, let's explore this.

Let's say that I'm a novice C++ programmer. I don't really know much about the language. But I have some basic knowledge.

Now, I've been told that when I write functions, I put a prototype in a header file so that other people can use it. But I also put the implementation in a source file, so that it stays hidden. So I write:
//header
RetType func_name(Type1 arg1, ...);

//source
RetType func_name(Type1 arg1, ...)
{
//implementation
}


OK, fine.

I've also been told about a different class of functions: template functions. For reasons I haven't been told and don't much care about (since I'm a novice), I have to put the implementation in the header file. So I know that if I type the word "template", then that function's implementation has to go into a header. So I always do this:
//header
template<typename T>
RetType func_name_template(T arg1, ...)
{
//implementation
}

//source doesn't exist.


OK, fine. So... explain to me, the novice C++ programmer, why this doesn't work:
//header
RetType func_name_concept(ConceptName arg1, ...);

//source
RetType func_name_concept(ConceptName arg1, ...)
{
//implementation
}

Explain to me, the novice C++ programmer, why this thing which doesn't look like a template suddenly became a template. Explain to me why I have to implement it in a header, even though it looks exactly like every other non-template function declaration/definition.

To the novice C++ programmer, it isn't "all just programming." Whether something is a template matters.

Oh, you could say, "well just put everything in a header." That's... insane. Compile times for C++ projects of significant size are already huge even when you try to only put what you need in headers. Adding the burden of shoving everything in a header is crazy.

Now, if you can promise me that the same version of C++ that will include this terse syntax will also include modules, I will immediately stop caring. Once that exists, then most of the differences between template and non-template functions will be erased. And therefore, so too can the syntactic differences.

But so long as there is a difference in how you implement template and non-template functions, I say that there should be an obvious difference in syntax too.
My issue is with, well, any syntax that declares a template without having to type either the word "template" or the use of "<>" brackets.
That ship has sailed:

auto plus = [](auto x, auto y) { return x+y; }

which even already decays to an ordinary pointer to function, etc.

That doesn't decay into a function pointer. It can't; the operator() is a template.


Clarifying Q: Are we mainly arguing about whether to require the three characters =, [, and ] ?
Except that there is a difference between creating a lambda (which creates a functor) and creating a function (which can be overloaded).

Not only has the ship sailed, but I for one like the direction it's sailing. I see no reason why functions should be forced to spell "template" and "<>". What value does it add? It's "just programming." In fact, if we didn't have backward compatibility issues with unnamed parameters and such, I'd personally probably be fine with just "auto plus(x,y){x+y}" as an equivalent function definition. That still doesn't lose any information.

Gratuitous syntax is often unnecessary and usually harmful. Saying

template<class T, class U>
auto(T x, U y) -> decltype(x+y) { return x+y; }

does not appear to me to contain any more information than

auto plus(auto x, auto y) { return x+y; }

does it?
If you take out the late specified return type (I specifically said that static deduction was fine), then I don't see the problem with the first one.


Requiring the verbose syntax is gratuitous, if the verbose syntax does not add information, does not serve to disambiguate anything, and does not highlight a dangerous operation or anything else I can see that deserves to have attention called to it.

There's a disturbing (to me and at least some others) trend in C++ these days: People seem to be very prone to wanting "more syntax" lately. It's rather Vasa-like, if only lexically. Let me channel certain influential committee members and say: 'People these days are always asking for more syntax! There's no proposal they've seen that they couldn't make uglier with more syntax!'

Important note: The point here is NOT terseness for terseness' sake. I am not arguing that terser is somehow better, that terseness is virtuous in itself. Too many people glorify languages because they're terser; fewer characters alone doesn't make code clearer. Rather, my point is to avoid gratuitous verbosity. At the other end of the pendulum, too many people glorify verbose syntax because they think _that_ is somehow inherently clearer; usually it isn't. So I am arguing that neither is verbosity virtuous in itself.

Herb
The virtue to me of the large syntax of templates is this:

Templates have to be treated differently from non-templates. They have different needs of where their implementations live. And because of those needs, templates make your code compile slower. Even ignoring the compile-time cost of template instantiation, your source has to go in the header. And if that header is included in more than one place, then the source for that template must be recompiled for every place it is included.

Therefore, the bulky template syntax pokes you in the eye every time you write something that's going to compile slower. It immediately lets you know that this function operates under fundamentally different rules than regular functions.

Again, if you could guarantee that we get modules alongside this syntax, I'd be fine, since using templates will not hurt your compile times nearly as much.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
John Spicer
2015-03-06 20:58:00 UTC
Permalink
Post by Herb Sutter
“if the declaration mentions ‘auto’ or a concept name, the compiler needs the definition, either to deduce something or to inline the body into the caller.” Right?
If you say "auto" or a concept name, it is a template. My interpretation of what Herb wrote, is that it was implying more than that.

john.
This surprised me so I asked John offline what he meant, and I think we’re not in disagreement. You can’t call those unless there are (also) definitions.
What I said is correct: If auto (or a concept name) is used in the return type or parameter type, the definition must be available “in a header.” And this is already true for auto return types.
I did not mean to imply that you couldn’t also have a forward declaration too (which you can have for function templates but not for auto returns), but it still must be accompanied by a definition which was the point under discussion, namely that the definition still has to be available in the header.
Note that I’m excluding the “extern template” case, which is a special case and about controlling where instantiations occur (or limiting them) rather than about writing the generally usable function template itself
 so IMO extern templates aren’t applicable to this question.
Herb
Sent: Friday, March 6, 2015 10:38 AM
Subject: [c++std-core-27231] Re: An implementation of enhanced auto deduction and abbreviated template syntax using Clang
Post by Herb Sutter
To the novice C++ programmer, it isn't "all just programming." Whether something is a template matters.
auto f() { 
 };
This is not a template, but must appear in a header. This is amazingly similar – and easy to teach as “if the declaration mentions ‘auto’ or a concept name, the compiler needs the definition, either to deduce something or to inline the body into the caller.” Right?
Actually, that is not right -- in fact, it is mostly wrong.
Only if the return type is deduced do you need a definition.
void f(auto,auto);
void g(ForwardIterator);
do not need definitions.
John.
Herb
PS – Since you mention “novices” writing templates, in my experience (and to my surprise) I’ve found that not only novices but also intermediate developers (like 5-7 year veterans) don’t write templates very much. [I expect this to change with concepts, for the good.] I discovered this by chance when I had a class exercise that included writing a very simple template, and as I walked through the class during the exercise I was surprised that most of the groups asked about the syntax for writing a template – a dead giveaway that they didn’t write templates very often, yet these were pretty experienced developers who used C++ every day, but just never needed to write templates much in their normal code. To validate that this wasn’t just an outlier group, I’ve watched that exercise in a number of classes over several years and found a similar result – the majority of even reasonably experienced C++ programmers asked about the syntax for how to write a template.
Sent: Friday, March 6, 2015 9:21 AM
Subject: Re: [c++std-core-27204] Re: An implementation of enhanced auto deduction and abbreviated template syntax using Clang
To paraphrase Stroustrup, it’s not about functional programming and object-oriented programming and generic programming
 “it’s all just programming.”
Post by Herb Sutter
Templates are a fundamentally different kind of construct
Why? Every full specialization of a function template is just a function.
OK, let's explore this.
Let's say that I'm a novice C++ programmer. I don't really know much about the language. But I have some basic knowledge.
//header
RetType func_name(Type1 arg1, ...);
//source
RetType func_name(Type1 arg1, ...)
{
//implementation
}
OK, fine.
//header
template<typename T>
RetType func_name_template(T arg1, ...)
{
//implementation
}
//source doesn't exist.
//header
RetType func_name_concept(ConceptName arg1, ...);
//source
RetType func_name_concept(ConceptName arg1, ...)
{
//implementation
}
Explain to me, the novice C++ programmer, why this thing which doesn't look like a template suddenly became a template. Explain to me why I have to implement it in a header, even though it looks exactly like every other non-template function declaration/definition.
To the novice C++ programmer, it isn't "all just programming." Whether something is a template matters.
Oh, you could say, "well just put everything in a header." That's... insane. Compile times for C++ projects of significant size are already huge even when you try to only put what you need in headers. Adding the burden of shoving everything in a header is crazy.
Now, if you can promise me that the same version of C++ that will include this terse syntax will also include modules, I will immediately stop caring. Once that exists, then most of the differences between template and non-template functions will be erased. And therefore, so too can the syntactic differences.
But so long as there is a difference in how you implement template and non-template functions, I say that there should be an obvious difference in syntax too.
Post by Herb Sutter
My issue is with, well, any syntax that declares a template without having to type either the word "template" or the use of "<>" brackets.
auto plus = [](auto x, auto y) { return x+y; }
which even already decays to an ordinary pointer to function, etc.
That doesn't decay into a function pointer. It can't; the operator() is a template.
Clarifying Q: Are we mainly arguing about whether to require the three characters =, [, and ] ?
Except that there is a difference between creating a lambda (which creates a functor) and creating a function (which can be overloaded).
Not only has the ship sailed, but I for one like the direction it’s sailing. I see no reason why functions should be forced to spell “template” and “<>”. What value does it add? It’s “just programming.” In fact, if we didn’t have backward compatibility issues with unnamed parameters and such, I’d personally probably be fine with just “auto plus(x,y){x+y}” as an equivalent function definition. That still doesn’t lose any information.
Gratuitous syntax is often unnecessary and usually harmful. Saying
template<class T, class U>
auto(T x, U y) -> decltype(x+y) { return x+y; }
does not appear to me to contain any more information than
auto plus(auto x, auto y) { return x+y; }
does it?
If you take out the late specified return type (I specifically said that static deduction was fine), then I don't see the problem with the first one.
Requiring the verbose syntax is gratuitous, if the verbose syntax does not add information, does not serve to disambiguate anything, and does not highlight a dangerous operation or anything else I can see that deserves to have attention called to it.
There’s a disturbing (to me and at least some others) trend in C++ these days: People seem to be very prone to wanting “more syntax” lately. It’s rather Vasa-like, if only lexically. Let me channel certain influential committee members and say: ‘People these days are always asking for more syntax! There’s no proposal they’ve seen that they couldn’t make uglier with more syntax!’
Important note: The point here is NOT terseness for terseness’ sake. I am not arguing that terser is somehow better, that terseness is virtuous in itself. Too many people glorify languages because they’re terser; fewer characters alone doesn’t make code clearer. Rather, my point is to avoid gratuitous verbosity. At the other end of the pendulum, too many people glorify verbose syntax because they think _that_ is somehow inherently clearer; usually it isn’t. So I am arguing that neither is verbosity virtuous in itself.
Herb
Templates have to be treated differently from non-templates. They have different needs of where their implementations live. And because of those needs, templates make your code compile slower. Even ignoring the compile-time cost of template instantiation, your source has to go in the header. And if that header is included in more than one place, then the source for that template must be recompiled for every place it is included.
Therefore, the bulky template syntax pokes you in the eye every time you write something that's going to compile slower. It immediately lets you know that this function operates under fundamentally different rules than regular functions.
Again, if you could guarantee that we get modules alongside this syntax, I'd be fine, since using templates will not hurt your compile times nearly as much.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Herb Sutter
2015-03-06 21:30:54 UTC
Permalink
Sorry for confusion, I was trying to word it generally to cover both auto returns (which we have already, so we already have a case where we require a definition without a keyword like "template" or "inline") and the proposed auto parameter (only the latter makes a template).

The observation was that both the current and proposes uses of "auto" in the declaration would equally require a definition to be available in the header, and that simply saying that is a teachable rule.

Thanks,

Herb


From: John Spicer [mailto:***@edg.com]
Sent: Friday, March 6, 2015 12:58 PM
To: c++std-***@accu.org
Cc: Nicol Bolas; std-***@isocpp.org; std-***@isocpp.org; ***@gmail.com
Subject: [c++std-core-27247] Re: An implementation of enhanced auto deduction and abbreviated template syntax using Clang

I think the confusion is that Herb wrote:

"if the declaration mentions 'auto' or a concept name, the compiler needs the definition, either to deduce something or to inline the body into the caller." Right?

If you say "auto" or a concept name, it is a template. My interpretation of what Herb wrote, is that it was implying more than that.

john.


On Mar 6, 2015, at 3:53 PM, Herb Sutter <***@microsoft.com<mailto:***@microsoft.com>> wrote:


This surprised me so I asked John offline what he meant, and I think we're not in disagreement. You can't call those unless there are (also) definitions.

What I said is correct: If auto (or a concept name) is used in the return type or parameter type, the definition must be available "in a header." And this is already true for auto return types.

I did not mean to imply that you couldn't also have a forward declaration too (which you can have for function templates but not for auto returns), but it still must be accompanied by a definition which was the point under discussion, namely that the definition still has to be available in the header.

Note that I'm excluding the "extern template" case, which is a special case and about controlling where instantiations occur (or limiting them) rather than about writing the generally usable function template itself... so IMO extern templates aren't applicable to this question.

Herb


From: John Spicer [mailto:***@edg.com<http://edg.com>]
Sent: Friday, March 6, 2015 10:38 AM
To: c++std-***@accu.org<mailto:c++std-***@accu.org>
Cc: Nicol Bolas; std-***@isocpp.org<mailto:std-***@isocpp.org>; std-***@isocpp.org<mailto:std-***@isocpp.org>; ***@gmail.com<mailto:***@gmail.com>
Subject: [c++std-core-27231] Re: An implementation of enhanced auto deduction and abbreviated template syntax using Clang
To the novice C++ programmer, it isn't "all just programming." Whether something is a template matters.
Why? Only because of where you put the definition, and that's (a) teachable and (b) not new because the same issue exists already with:

auto f() { ... };

This is not a template, but must appear in a header. This is amazingly similar - and easy to teach as "if the declaration mentions 'auto' or a concept name, the compiler needs the definition, either to deduce something or to inline the body into the caller." Right?

Actually, that is not right -- in fact, it is mostly wrong.

Only if the return type is deduced do you need a definition.

So:

void f(auto,auto);
void g(ForwardIterator);

do not need definitions.

John.




Herb

PS - Since you mention "novices" writing templates, in my experience (and to my surprise) I've found that not only novices but also intermediate developers (like 5-7 year veterans) don't write templates very much. [I expect this to change with concepts, for the good.] I discovered this by chance when I had a class exercise that included writing a very simple template, and as I walked through the class during the exercise I was surprised that most of the groups asked about the syntax for writing a template - a dead giveaway that they didn't write templates very often, yet these were pretty experienced developers who used C++ every day, but just never needed to write templates much in their normal code. To validate that this wasn't just an outlier group, I've watched that exercise in a number of classes over several years and found a similar result - the majority of even reasonably experienced C++ programmers asked about the syntax for how to write a template.



From: Nicol Bolas [mailto:***@gmail.com<http://gmail.com>]
Sent: Friday, March 6, 2015 9:21 AM
To: std-***@isocpp.org<mailto:std-***@isocpp.org>
Cc: c++std-***@accu.org<mailto:c++std-***@accu.org>; std-***@isocpp.org<mailto:std-***@isocpp.org>; ***@gmail.com<mailto:***@gmail.com>; Herb Sutter
Subject: Re: [c++std-core-27204] Re: An implementation of enhanced auto deduction and abbreviated template syntax using Clang

On Thursday, March 5, 2015 at 7:24:32 PM UTC-5, Herb Sutter wrote:
To paraphrase Stroustrup, it's not about functional programming and object-oriented programming and generic programming... "it's all just programming."
Templates are a fundamentally different kind of construct
Why? Every full specialization of a function template is just a function.

OK, let's explore this.

Let's say that I'm a novice C++ programmer. I don't really know much about the language. But I have some basic knowledge.

Now, I've been told that when I write functions, I put a prototype in a header file so that other people can use it. But I also put the implementation in a source file, so that it stays hidden. So I write:
//header
RetType func_name(Type1 arg1, ...);

//source
RetType func_name(Type1 arg1, ...)
{
//implementation
}


OK, fine.

I've also been told about a different class of functions: template functions. For reasons I haven't been told and don't much care about (since I'm a novice), I have to put the implementation in the header file. So I know that if I type the word "template", then that function's implementation has to go into a header. So I always do this:
//header
template<typename T>
RetType func_name_template(T arg1, ...)
{
//implementation
}

//source doesn't exist.


OK, fine. So... explain to me, the novice C++ programmer, why this doesn't work:
//header
RetType func_name_concept(ConceptName arg1, ...);

//source
RetType func_name_concept(ConceptName arg1, ...)
{
//implementation
}

Explain to me, the novice C++ programmer, why this thing which doesn't look like a template suddenly became a template. Explain to me why I have to implement it in a header, even though it looks exactly like every other non-template function declaration/definition.

To the novice C++ programmer, it isn't "all just programming." Whether something is a template matters.

Oh, you could say, "well just put everything in a header." That's... insane. Compile times for C++ projects of significant size are already huge even when you try to only put what you need in headers. Adding the burden of shoving everything in a header is crazy.

Now, if you can promise me that the same version of C++ that will include this terse syntax will also include modules, I will immediately stop caring. Once that exists, then most of the differences between template and non-template functions will be erased. And therefore, so too can the syntactic differences.

But so long as there is a difference in how you implement template and non-template functions, I say that there should be an obvious difference in syntax too.
My issue is with, well, any syntax that declares a template without having to type either the word "template" or the use of "<>" brackets.
That ship has sailed:

auto plus = [](auto x, auto y) { return x+y; }

which even already decays to an ordinary pointer to function, etc.

That doesn't decay into a function pointer. It can't; the operator() is a template.


Clarifying Q: Are we mainly arguing about whether to require the three characters =, [, and ] ?
Except that there is a difference between creating a lambda (which creates a functor) and creating a function (which can be overloaded).

Not only has the ship sailed, but I for one like the direction it's sailing. I see no reason why functions should be forced to spell "template" and "<>". What value does it add? It's "just programming." In fact, if we didn't have backward compatibility issues with unnamed parameters and such, I'd personally probably be fine with just "auto plus(x,y){x+y}" as an equivalent function definition. That still doesn't lose any information.

Gratuitous syntax is often unnecessary and usually harmful. Saying

template<class T, class U>
auto(T x, U y) -> decltype(x+y) { return x+y; }

does not appear to me to contain any more information than

auto plus(auto x, auto y) { return x+y; }

does it?
If you take out the late specified return type (I specifically said that static deduction was fine), then I don't see the problem with the first one.


Requiring the verbose syntax is gratuitous, if the verbose syntax does not add information, does not serve to disambiguate anything, and does not highlight a dangerous operation or anything else I can see that deserves to have attention called to it.

There's a disturbing (to me and at least some others) trend in C++ these days: People seem to be very prone to wanting "more syntax" lately. It's rather Vasa-like, if only lexically. Let me channel certain influential committee members and say: 'People these days are always asking for more syntax! There's no proposal they've seen that they couldn't make uglier with more syntax!'

Important note: The point here is NOT terseness for terseness' sake. I am not arguing that terser is somehow better, that terseness is virtuous in itself. Too many people glorify languages because they're terser; fewer characters alone doesn't make code clearer. Rather, my point is to avoid gratuitous verbosity. At the other end of the pendulum, too many people glorify verbose syntax because they think _that_ is somehow inherently clearer; usually it isn't. So I am arguing that neither is verbosity virtuous in itself.

Herb
The virtue to me of the large syntax of templates is this:

Templates have to be treated differently from non-templates. They have different needs of where their implementations live. And because of those needs, templates make your code compile slower. Even ignoring the compile-time cost of template instantiation, your source has to go in the header. And if that header is included in more than one place, then the source for that template must be recompiled for every place it is included.

Therefore, the bulky template syntax pokes you in the eye every time you write something that's going to compile slower. It immediately lets you know that this function operates under fundamentally different rules than regular functions.

Again, if you could guarantee that we get modules alongside this syntax, I'd be fine, since using templates will not hurt your compile times nearly as much.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
'Geoffrey Romer' via ISO C++ Standard - Discussion
2015-03-06 19:27:21 UTC
Permalink
Post by Nicol Bolas
To the novice C++ programmer, it *isn't* "all just programming."
Whether something is a template *matters*.
Why? Only because of where you put the definition, and that’s (a)
auto f() { 
 };
This is not a template, but must appear in a header. This is amazingly
similar – and easy to teach as “if the declaration mentions ‘auto’ or a
concept name, the compiler needs the definition, either to deduce something
or to inline the body into the caller.” Right?
Herb
PS – Since you mention “novices” writing templates, in my experience (and
to my surprise) I’ve found that not only novices but also intermediate
developers (like 5-7 year veterans) don’t write templates very much. [I
expect this to change with concepts, for the good.] I discovered this by
chance when I had a class exercise that included writing a very simple
template, and as I walked through the class during the exercise I was
surprised that most of the groups asked about the syntax for writing a
template – a dead giveaway that they didn’t write templates very often, yet
these were pretty experienced developers who used C++ every day, but just
never needed to write templates much in their normal code. To validate that
this wasn’t just an outlier group, I’ve watched that exercise in a number
of classes over several years and found a similar result – the majority of
even reasonably experienced C++ programmers asked about the syntax for how
to write a template.
This very much matches my experience- as far as I can tell, the vast
majority of C++ code is non-template code. But why is that surprising, and
why do you expect concepts to change it?
*Sent:* Friday, March 6, 2015 9:21 AM
Herb Sutter
*Subject:* Re: [c++std-core-27204] Re: An implementation of enhanced auto
deduction and abbreviated template syntax using Clang
To paraphrase Stroustrup, it’s not about functional programming and
object-oriented programming and generic programming
 “it’s all *just
programming*.”
Post by Nicol Bolas
Templates are a fundamentally different kind of construct
Why? Every full specialization of a function template is just a function.
OK, let's explore this.
Let's say that I'm a novice C++ programmer. I don't really know much about
the language. But I have some basic knowledge.
Now, I've been told that when I write functions, I put a prototype in a
header file so that other people can use it. But I also put the
//header
RetType func_name(Type1 arg1, ...);
//source
RetType func_name(Type1 arg1, ...)
{
//implementation
}
OK, fine.
I've also been told about a different class of functions: template
functions. For reasons I haven't been told and don't much care about (since
I'm a novice), I have to put the implementation in the header file. So I
know that if I type the word "template", then that function's
//header
template<typename T>
RetType func_name_template(T arg1, ...)
{
//implementation
}
//source doesn't exist.
//header
RetType func_name_concept(ConceptName arg1, ...);
//source
RetType func_name_concept(ConceptName arg1, ...)
{
//implementation
}
Explain to me, the novice C++ programmer, why this thing which doesn't
look like a template suddenly *became* a template. Explain to me why I
have to implement it in a header, even though it looks exactly like every
other non-template function declaration/definition.
To the novice C++ programmer, it *isn't* "all just programming." Whether
something is a template *matters*.
Oh, you could say, "well just put *everything* in a header." That's...
insane. Compile times for C++ projects of significant size are already huge
even when you try to only put what you need in headers. Adding the burden
of shoving everything in a header is crazy.
Now, if you can promise me that the same version of C++ that will include
this terse syntax will also include *modules*, I will immediately stop
caring. Once that exists, then most of the differences between template and
non-template functions will be erased. And therefore, so too can the
syntactic differences.
But so long as there is a difference in how you implement template and
non-template functions, I say that there should be an obvious difference in
syntax too.
Post by Nicol Bolas
My issue is with, well, any syntax that declares a template without
having to type either the word "template" or the use of "<>" brackets.
auto plus = [](auto x, auto y) { return x+y; }
which even already decays to an ordinary pointer to function, etc.
That doesn't decay into a function pointer. It can't; the operator() is a template.
Clarifying Q: Are we mainly arguing about whether to require the three
characters =, [, and ] ?
Except that there is a difference between creating a lambda (which
creates a functor) and creating a function (which can be overloaded).
Not only has the ship sailed, but I for one like the direction it’s
sailing. I see no reason why functions should be forced to spell “template”
and “<>”. What value does it add? It’s “just programming.” In fact, if we
didn’t have backward compatibility issues with unnamed parameters and such,
I’d personally probably be fine with just “auto plus(x,y){x+y}” as an
equivalent function definition. That still doesn’t lose any information.
Gratuitous syntax is often unnecessary and usually harmful. Saying
template<class T, class U>
auto(T x, U y) -> decltype(x+y) { return x+y; }
does not appear to me to contain any more information than
auto plus(auto x, auto y) { return x+y; }
does it?
If you take out the late specified return type (I specifically said that
static deduction was fine), then I don't see the problem with the first one.
Requiring the verbose syntax is gratuitous, if the verbose syntax does
not add information, does not serve to disambiguate anything, and does not
highlight a dangerous operation or anything else I can see that deserves to
have attention called to it.
There’s a disturbing (to me and at least some others) trend in C++ these
days: People seem to be very prone to wanting “more syntax” lately. It’s
rather Vasa-like, if only lexically. Let me channel certain influential
committee members and say: ‘People these days are always asking for more
syntax! There’s no proposal they’ve seen that they couldn’t make uglier
with more syntax!’
Important note: The point here is NOT terseness for terseness’ sake. I am
not arguing that terser is somehow better, that terseness is virtuous in
itself. Too many people glorify languages because they’re terser; fewer
characters alone doesn’t make code clearer. Rather, my point is to avoid
gratuitous verbosity. At the other end of the pendulum, too many people
glorify verbose syntax because they think _that_ is somehow inherently
clearer; usually it isn’t. So I am arguing that neither is verbosity
virtuous in itself.
Herb
Templates have to be treated differently from non-templates. They have
different needs of where their implementations live. And because of those
needs, templates make your code compile slower. Even ignoring the
compile-time cost of template instantiation, your source has to go in the
header. And if that header is included in more than one place, then the
source for that template must be recompiled for every place it is included.
Therefore, the bulky template syntax pokes you in the eye every time you
write something that's going to compile slower. It immediately lets you
know that this function operates under fundamentally different rules than
regular functions.
Again, if you could guarantee that we get modules alongside this syntax,
I'd be fine, since using templates will not hurt your compile times nearly
as much.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Nicol Bolas
2015-03-06 20:11:39 UTC
Permalink
Post by 'Geoffrey Romer' via ISO C++ Standard - Discussion
Post by Nicol Bolas
To the novice C++ programmer, it *isn't* "all just programming."
Whether something is a template *matters*.
Why? Only because of where you put the definition, and that’s (a)
auto f() { 
 };
This is not a template, but must appear in a header. This is amazingly
similar – and easy to teach as “if the declaration mentions ‘auto’ or a
concept name, the compiler needs the definition, either to deduce something
or to inline the body into the caller.” Right?
Herb
PS – Since you mention “novices” writing templates, in my experience (and
to my surprise) I’ve found that not only novices but also intermediate
developers (like 5-7 year veterans) don’t write templates very much. [I
expect this to change with concepts, for the good.] I discovered this by
chance when I had a class exercise that included writing a very simple
template, and as I walked through the class during the exercise I was
surprised that most of the groups asked about the syntax for writing a
template – a dead giveaway that they didn’t write templates very often, yet
these were pretty experienced developers who used C++ every day, but just
never needed to write templates much in their normal code. To validate that
this wasn’t just an outlier group, I’ve watched that exercise in a number
of classes over several years and found a similar result – the majority of
even reasonably experienced C++ programmers asked about the syntax for how
to write a template.
This very much matches my experience- as far as I can tell, the vast
majority of C++ code is non-template code. But why is that surprising, and
why do you expect concepts to change it?
That's my experience as well. However, I can also say that concepts is not
what would get me to write more templates, as concepts (as it is currently
proposed) only makes *using* templates easier (by declaring up-front what
the requirements are). It doesn't make implementing a function easier (by
checking each point of use to see if it is a required behavior).

Even with that, it wouldn't make me write more templates. I'd still need
modules for that; compile times are just too long for heavily templated
code. Debugging and testing requires lots of compilation, so things that
make compilation slower will (continue to) be avoided.

I just wish I didn't have to avoid useful language features because of the
compilation mechanism.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
'Geoffrey Romer' via ISO C++ Standard - Discussion
2015-03-06 21:25:49 UTC
Permalink
Post by Nicol Bolas
Post by 'Geoffrey Romer' via ISO C++ Standard - Discussion
Post by Nicol Bolas
To the novice C++ programmer, it *isn't* "all just programming."
Whether something is a template *matters*.
Why? Only because of where you put the definition, and that’s (a)
auto f() { 
 };
This is not a template, but must appear in a header. This is amazingly
similar – and easy to teach as “if the declaration mentions ‘auto’ or a
concept name, the compiler needs the definition, either to deduce something
or to inline the body into the caller.” Right?
Herb
PS – Since you mention “novices” writing templates, in my experience
(and to my surprise) I’ve found that not only novices but also intermediate
developers (like 5-7 year veterans) don’t write templates very much. [I
expect this to change with concepts, for the good.] I discovered this by
chance when I had a class exercise that included writing a very simple
template, and as I walked through the class during the exercise I was
surprised that most of the groups asked about the syntax for writing a
template – a dead giveaway that they didn’t write templates very often, yet
these were pretty experienced developers who used C++ every day, but just
never needed to write templates much in their normal code. To validate that
this wasn’t just an outlier group, I’ve watched that exercise in a number
of classes over several years and found a similar result – the majority of
even reasonably experienced C++ programmers asked about the syntax for how
to write a template.
This very much matches my experience- as far as I can tell, the vast
majority of C++ code is non-template code. But why is that surprising, and
why do you expect concepts to change it?
That's my experience as well. However, I can also say that concepts is not
what would get me to write more templates, as concepts (as it is currently
proposed) only makes *using* templates easier (by declaring up-front what
the requirements are). It doesn't make implementing a function easier (by
checking each point of use to see if it is a required behavior).
Interesting; my impression was the other way around, that concepts make it
easier to write templates, but not really easier to use them. The main
functional advantage that I see with concepts is that they let you control
the overload set much more easily (and much more readably), and that helps
template authors, not template users. I see your point about declaring the
requirements up-front, but decent template libraries already do that in the
documentation; I'm not sure that formalizing those requirements in code
will really help users much.

Even with that, it wouldn't make me write more templates. I'd still need
Post by Nicol Bolas
modules for that; compile times are just too long for heavily templated
code. Debugging and testing requires lots of compilation, so things that
make compilation slower will (continue to) be avoided.
I just wish I didn't have to avoid useful language features because of the
compilation mechanism.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Nicol Bolas
2015-03-06 22:23:17 UTC
Permalink
Post by 'Geoffrey Romer' via ISO C++ Standard - Discussion
Post by Nicol Bolas
Post by 'Geoffrey Romer' via ISO C++ Standard - Discussion
Post by Nicol Bolas
To the novice C++ programmer, it *isn't* "all just programming."
Whether something is a template *matters*.
Why? Only because of where you put the definition, and that’s (a)
auto f() { 
 };
This is not a template, but must appear in a header. This is amazingly
similar – and easy to teach as “if the declaration mentions ‘auto’ or a
concept name, the compiler needs the definition, either to deduce something
or to inline the body into the caller.” Right?
Herb
PS – Since you mention “novices” writing templates, in my experience
(and to my surprise) I’ve found that not only novices but also intermediate
developers (like 5-7 year veterans) don’t write templates very much. [I
expect this to change with concepts, for the good.] I discovered this by
chance when I had a class exercise that included writing a very simple
template, and as I walked through the class during the exercise I was
surprised that most of the groups asked about the syntax for writing a
template – a dead giveaway that they didn’t write templates very often, yet
these were pretty experienced developers who used C++ every day, but just
never needed to write templates much in their normal code. To validate that
this wasn’t just an outlier group, I’ve watched that exercise in a number
of classes over several years and found a similar result – the majority of
even reasonably experienced C++ programmers asked about the syntax for how
to write a template.
This very much matches my experience- as far as I can tell, the vast
majority of C++ code is non-template code. But why is that surprising, and
why do you expect concepts to change it?
That's my experience as well. However, I can also say that concepts is
not what would get me to write more templates, as concepts (as it is
currently proposed) only makes *using* templates easier (by declaring
up-front what the requirements are). It doesn't make implementing a
function easier (by checking each point of use to see if it is a required
behavior).
Interesting; my impression was the other way around, that concepts make it
easier to write templates, but not really easier to use them. The main
functional advantage that I see with concepts is that they let you control
the overload set much more easily (and much more readably), and that helps
template authors, not template users. I see your point about declaring the
requirements up-front, but decent template libraries already do that in the
documentation; I'm not sure that formalizing those requirements in code
will really help users much.
You assume that users actually read that documentation. Or remember it when
they read it.

If someone gives you an abstract base class to implement, the requirements
are listed right there, in the language. You have to derive from that
class; derive from the wrong one, and you'll get a compiler error
somewhere. You have to override all pure-virtual methods; type the method
name wrong, and you get a compiler error somewhere (either due to the class
still being abstract or because you used "override" and there was no base
class function). And so forth.

If I give a non-moveable type to std::vector<T>, it will give me some kind
of compiler error. What kind? God only knows, but more likely than not, it
will be long, obtuse, and generally indecipherable if you've never seen it
before. This is because the compilation failure happens somewhere in the
instantiation of std::vector<T> when it tries to actually use your type in
a way that it can't be used. So the compiler will point to the guts of
std::vector<T>'s implementation, rather than at your code where the actual
mistake was made.

If I give a non-moveable type to std::vector<MoveConstructable>, it will
give me a much cleaner error message. With a semi-decent compiler, it'll
point you right to the line where you instantiated your std::vector and say
"Hey, your type T isn't MoveConstructable, because it doesn't have a move
constructor." At the very least, I won't get a giant spew of template stuff.

Concepts are great at telling me what I did wrong when I misuse a template.
Which means I will feel much more confident that, if it compiled, I'm using
the template correctly.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
'Geoffrey Romer' via ISO C++ Standard - Discussion
2015-03-07 00:33:33 UTC
Permalink
Post by Nicol Bolas
Post by 'Geoffrey Romer' via ISO C++ Standard - Discussion
Post by Nicol Bolas
Post by 'Geoffrey Romer' via ISO C++ Standard - Discussion
Post by Nicol Bolas
To the novice C++ programmer, it *isn't* "all just programming."
Whether something is a template *matters*.
Why? Only because of where you put the definition, and that’s (a)
auto f() { 
 };
This is not a template, but must appear in a header. This is amazingly
similar – and easy to teach as “if the declaration mentions ‘auto’ or a
concept name, the compiler needs the definition, either to deduce something
or to inline the body into the caller.” Right?
Herb
PS – Since you mention “novices” writing templates, in my experience
(and to my surprise) I’ve found that not only novices but also intermediate
developers (like 5-7 year veterans) don’t write templates very much. [I
expect this to change with concepts, for the good.] I discovered this by
chance when I had a class exercise that included writing a very simple
template, and as I walked through the class during the exercise I was
surprised that most of the groups asked about the syntax for writing a
template – a dead giveaway that they didn’t write templates very often, yet
these were pretty experienced developers who used C++ every day, but just
never needed to write templates much in their normal code. To validate that
this wasn’t just an outlier group, I’ve watched that exercise in a number
of classes over several years and found a similar result – the majority of
even reasonably experienced C++ programmers asked about the syntax for how
to write a template.
This very much matches my experience- as far as I can tell, the vast
majority of C++ code is non-template code. But why is that surprising, and
why do you expect concepts to change it?
That's my experience as well. However, I can also say that concepts is
not what would get me to write more templates, as concepts (as it is
currently proposed) only makes *using* templates easier (by declaring
up-front what the requirements are). It doesn't make implementing a
function easier (by checking each point of use to see if it is a required
behavior).
Interesting; my impression was the other way around, that concepts make
it easier to write templates, but not really easier to use them. The main
functional advantage that I see with concepts is that they let you control
the overload set much more easily (and much more readably), and that helps
template authors, not template users. I see your point about declaring the
requirements up-front, but decent template libraries already do that in the
documentation; I'm not sure that formalizing those requirements in code
will really help users much.
You assume that users actually read that documentation. Or remember it
when they read it.
If someone gives you an abstract base class to implement, the requirements
are listed right there, in the language. You have to derive from that
class; derive from the wrong one, and you'll get a compiler error
somewhere. You have to override all pure-virtual methods; type the method
name wrong, and you get a compiler error somewhere (either due to the class
still being abstract or because you used "override" and there was no base
class function). And so forth.
_Some_ of the requirements are embedded in the code, but not all. Those
methods I'm overriding probably have contracts, and the compiler will not
be able to tell me when I violate them. There's just no helping the
programmers who don't read the documentation, but I think they're a
minority.
Post by Nicol Bolas
If I give a non-moveable type to std::vector<T>, it will give me some kind
of compiler error. What kind? God only knows, but more likely than not, it
will be long, obtuse, and generally indecipherable if you've never seen it
before. This is because the compilation failure happens somewhere in the
instantiation of std::vector<T> when it tries to actually use your type in
a way that it can't be used. So the compiler will point to the guts of
std::vector<T>'s implementation, rather than at your code where the actual
mistake was made.
If I give a non-moveable type to std::vector<MoveConstructable>, it will
give me a much cleaner error message. With a semi-decent compiler, it'll
point you right to the line where you instantiated your std::vector and say
"Hey, your type T isn't MoveConstructable, because it doesn't have a move
constructor." At the very least, I won't get a giant spew of template stuff.
Concepts are great at telling me what I did wrong when I misuse a
template. Which means I will feel much more confident that, if it compiled,
I'm using the template correctly.
I grant you that concepts have the potential to improve template error
messages, but as your example showed, the errors that they catch tend to be
errors that would have been caught anyway by ordinary type checking, so I
don't see how your increased confidence can be justified.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Nevin Liber
2015-03-06 18:56:22 UTC
Permalink
Post by Herb Sutter
auto plus = [](auto x, auto y) { return x+y; }
Post by Herb Sutter
which even already decays to an ordinary pointer to function, etc.
That doesn't decay into a function pointer. It can't; the operator() is a
template.
This code seems to work:

using fn = int (*)(int, int);

fn f = plus;

std::cout << f(2, 3) << std::endl;
--
Nevin ":-)" Liber <mailto:***@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Thiago Macieira
2015-03-06 01:03:38 UTC
Permalink
Post by Faisal Vali
pair<auto...> f() { return make_pair([] { }, [] { }); }
vector<auto> v = vector<int>();
What's the value of this syntax? Is it only to make it a compiler error if the
RHS isn't the type I had on the left?

That is, is it to make the following a compilation error:

std::vector<auto> v = someFunction();

if someFunction() returned QVector<int> instead of std::vector<int>?

Or is this syntax going to deduce the template parameters for the LHS from the
template parameters from the RHS, then convert? In other words, is the
following meant to be allowed?

template <typename T> struct S1 {};
template <typename T> struct S2
{
S2() = default;
S2(X<T>) {}
};

S1<int> someFunction();

...
S2<auto> v = someFunction();
// v is S2<int>

If that is the case, what are the rules for when the RHS has more template
parameters than the LHS? Just silently drop? (example: converting from
std::vector<T, Allocator> to QVector<T>).

And if the LHS has more parameters but those have default values, will it also
be allowed (from QVector<T> to std::vector<T, Allocator = allocator<T>>)?
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
Loading...