better-cpp-syntax icon indicating copy to clipboard operation
better-cpp-syntax copied to clipboard

Template definition needs multiple fixes

Open matter123 opened this issue 6 years ago • 8 comments

Not entirely sure if this is a duplicate of #106, but in the following example. Typename (note the capitalization) has the scope storage.type.template.argument.Typename.cpp The use of storage.type causes many themes to color Typename the same as a keyword. This can cause people to incorrectly believe that they are creating a standard type template, when in fact they are creating a non-type template.

template <Typename foo>
class foo;
Screen Shot 2019-06-19 at 19 09 52

matter123 avatar Jun 20 '19 02:06 matter123

Next thing on my list is to rewrite the template definition syntax from scratch. I agree it should be change, to be honest though, I don't know the meanings/use-case of the more complicated options. I can't even really tell the difference between <typename T> and <class T>. If you have a good grasp on it I'd be happy to learn, otherwise I'll probably take the time another day to read https://en.cppreference.com/w/cpp/language/templates and mess around with it until I figure it out. Once I know the behavior we can find a better tag name.

After this next change, I think all the template definition issues will be permanently solved.

jeff-hykin avatar Jun 20 '19 03:06 jeff-hykin

typename and class are identical when used inside a template definition

matter123 avatar Jun 20 '19 04:06 matter123

Ignoring C++20 (concepts) for simplicity. So generally. A template definition contains 0 or more template parameters. Template parameters come in four forms:

type parameter:

Probably the most common, has the form of typename|class Name = type-expression. Both the name and default type are optional. i.e. all of the below are valid

  • template<typename>
  • template<class Foo>
  • template<typename = A>
  • template<typename Alloc = std::allocator<T>> The type expression is any expression that evaluates into a type.

non type parameter:

This is used when you want to template on some compile time value. See std::array. These have the form of Type Name = expression and should follow the same rules for parameters.

template paramaters

Used when you want your type paramter to itself be a template. Basically a nested template definition followed by a type paramater. Example:

  • template<class A, template<class B> class C = std::deque<A>>

paramteer packs

Adds ... after typename or class or the Type.

matter123 avatar Jun 20 '19 04:06 matter123

I'm going to turn this into a major issue and close the other ones since they're related and are going to be fixed all at once

Official Syntax: https://en.cppreference.com/w/cpp/language/function_template

  1. Redo the scope names
  2. Fix the defaulted matching #106 #208 #245
  3. Add templated return types #79

This is the next major task on the todo list

jeff-hykin avatar Jun 25 '19 00:06 jeff-hykin

Just as an FYI, I added :template_call_range to the :template_call_context so that now it can match nested template calls. I did this mostly because there was an example where it failed inside of the parameters and caused the whole rest of the file to be screwed up, and it seems more common to have a nested template call than a template call with a <

jeff-hykin avatar Jun 26 '19 21:06 jeff-hykin

Posting as this example shows many of the previously mentioned issues with templates.

Example:

template <class U,
		class = std::enable_if_t<std::is_constructible_v<T, U &&> &&
						std::is_convertible_v<U &&, T>>>
constexpr propagate_const(propagate_const<U> &&pu) {}

Screenshot from 2019-06-30 00-19-06

On line 2 you can see keywords with no highlighting. On line 2, U is yellow and T is purple, however on line 3 they are swapped. It's not clear why enable_if is yellow but is_constructible_v is purple.

matter123 avatar Jun 30 '19 06:06 matter123

Test cases:

template<> // empty template
template<class> // unnamed parameter
template<typename>
template<class T> // named parameter
template<size_t I> // non-type parameter
template<class =void> // defaulted type parameter
template<size_t = 0> // defaulted non type parameter
template<class T, size_t I, class A = my::allocator<T, I>> // complex template
template<class...> // unnamed param-pack
template<size_t...> // unnamed non-type param-pack
template<class A, class...B> // named param pack
template<class A, template<class B> class C = std::deque<A>> // template template

matter123 avatar Nov 22 '19 19:11 matter123

2 more test cases for my issue:

template<class A, typename B> // mixed type-parameter-key
template<typename A, class B> // mixed type-parameter-key

UnsaidAverage avatar Apr 23 '20 01:04 UnsaidAverage