template blocks

113 views
Skip to first unread message

Douglas Boffey

unread,
May 22, 2015, 11:20:25 AM5/22/15
to std-pr...@isocpp.org
Consider:

template <typename T>
class Foo {
// whatever
public:
void bar();
void baz();
void another_fn();
// ...
};

To define the functions, you would have to write:

template <typename T>
void Foo::bar() { /* ... */ }

template <typename T>
void Foo::baz() { /* ... */ }

template <typename T>
void Foo::another_fn() { /* ... */ }

Wouldn’t it be better if we could write:

template <typename T> {
void Foo::bar() { /* ... */ }
void Foo::baz() { /* ... */ }
void Foo::another_fn() { /* ... */ }
}

Pro:
- less typing (although that is not the motivating reason)
- cleaner, clearer syntax, improving maintainability
- easier to check correctness

What do people think?

Ville Voutilainen

unread,
May 22, 2015, 11:23:13 AM5/22/15
to std-pr...@isocpp.org
I don't see how this is superior to writing the brief-version as a synopsis
comment and just writing the actual class definition with the member function
template definitions in it.

John Yates

unread,
May 22, 2015, 11:29:35 AM5/22/15
to std-pr...@isocpp.org
On Fri, May 22, 2015 at 11:23 AM, Ville Voutilainen <ville.vo...@gmail.com> wrote:
I don't see how this is superior to writing the brief-version as a synopsis
comment

Consistency of comments are not checked by the compiler and hence inevitably suffer bit rot.
 
and just writing the actual class definition with the member function
template definitions in it.

Does not work for specialization nor explicit instantiation outside of the header.

/john

Ville Voutilainen

unread,
May 22, 2015, 11:32:53 AM5/22/15
to std-pr...@isocpp.org
On 22 May 2015 at 18:29, John Yates <jo...@yates-sheets.org> wrote:
> On Fri, May 22, 2015 at 11:23 AM, Ville Voutilainen
> <ville.vo...@gmail.com> wrote:
>>
>> I don't see how this is superior to writing the brief-version as a
>> synopsis
>> comment
>
>
> Consistency of comments are not checked by the compiler and hence inevitably
> suffer bit rot.

I don't see how that's inevitable. The author would be producing a
brief synopsis
that his users would rely on, if that synopsis bitrots, the users will complain.

>
>>
>> and just writing the actual class definition with the member function
>> template definitions in it.
>
>
> Does not work for specialization nor explicit instantiation outside of the
> header.


I am unconvinced those are common enough to motivate a language change
to support such definition-blocks.

Douglas Boffey

unread,
May 22, 2015, 11:34:50 AM5/22/15
to std-pr...@isocpp.org
> just writing the actual class definition with the member function
> template definitions in it.

I was under the impression that writing the definitions of member
functions within a class definition was a pretty strong hint that the
compiler should inline the functions in code.
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposal...@isocpp.org.
> To post to this group, send email to std-pr...@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>

Ville Voutilainen

unread,
May 22, 2015, 11:45:36 AM5/22/15
to std-pr...@isocpp.org
On 22 May 2015 at 18:34, Douglas Boffey <douglas...@gmail.com> wrote:
>> just writing the actual class definition with the member function
>> template definitions in it.
>
> I was under the impression that writing the definitions of member
> functions within a class definition was a pretty strong hint that the
> compiler should inline the functions in code.


That's a red herring, this thing is a class template so the member function
bodies need to be visible to users anyway, so they are eligible for such
inlining regardless of whether they are in the class definition or outside it.

Christopher Horvath

unread,
May 22, 2015, 12:25:51 PM5/22/15
to std-pr...@isocpp.org
I think this is an excellent idea.  I've wanted this so much that in the past I've made all of my free functions static members of a dummy struct and written them all inline, just to avoid the notational bloat.

That's really what this is about - notational bloat, which impedes readability, comprehension, and overall "ease".  

This:

template <typename T> {
  void Foo::bar() { /* ... */ }
  void Foo::baz() { /* ... */ }
  void Foo::another_fn() { /* ... */ }
}

is easier to read, write, port, copy, and grok, than this:

template <typename T>
void Foo::bar() { /* ... */ }

template <typename T>
void Foo::baz() { /* ... */ }

template <typename T>
void Foo::another_fn() { /* ... */ }

I would love to see this, purely from the perspective of elegance.


Andrey Semashev

unread,
May 22, 2015, 12:35:04 PM5/22/15
to std-pr...@isocpp.org
That syntax confusing as it doesn't take into account member template
functions or nested template classes.

Johannes Schaub

unread,
May 22, 2015, 1:41:56 PM5/22/15
to std-pr...@isocpp.org

I don't see why that shoukd not work. I like the idea. Variables declared in it automatically could become variable templates.

Andrey Semashev

unread,
May 22, 2015, 3:13:07 PM5/22/15
to std-pr...@isocpp.org
On Friday 22 May 2015 19:41:55 Johannes Schaub wrote:
> I don't see why that shoukd not work.

It will only work if you specify template arguments in every definition, i.e.:

template <typename T> {

void Foo<T>::bar() { /* ... */ }
void Foo<T>::baz() { /* ... */ }
void Foo<T>::another_fn() { /* ... */ }

}

or

template <typename T> {

void Foo::bar<T>() { /* ... */ }
void Foo::baz<T>() { /* ... */ }
void Foo::another_fn<T>() { /* ... */ }

}

or

template <typename T>
template <typename U> {

void Foo<T>::bar<U>() { /* ... */ }
void Foo<T>::baz<U>() { /* ... */ }
void Foo<T>::another_fn<U>() { /* ... */ }

}

Otherwise the definition would be ambiguous. Personally, I don't think there's
much benefit from this change.

> Variables declared in it automatically could become variable templates.

That would most certainly be a gotcha for me.

Douglas Boffey

unread,
May 23, 2015, 5:35:54 AM5/23/15
to std-pr...@isocpp.org
No one is arguing that class templates can not be visible. I am
claiming there is a semantic difference, equivalent to using the
‘inline’ specifier for a function. Admittedly, the compiler can
ignore such hints.

Therefore, with respect, it is not the red herring you claim.

Ville Voutilainen

unread,
May 23, 2015, 5:45:52 AM5/23/15
to std-pr...@isocpp.org
On 23 May 2015 at 12:35, Douglas Boffey <douglas...@gmail.com> wrote:
>>> I was under the impression that writing the definitions of member
>>> functions within a class definition was a pretty strong hint that the
>>> compiler should inline the functions in code.
>> That's a red herring, this thing is a class template so the member function
>> bodies need to be visible to users anyway, so they are eligible for such
>> inlining regardless of whether they are in the class definition or outside
>> it.
> No one is arguing that class templates can not be visible. I am
> claiming there is a semantic difference, equivalent to using the
> ‘inline’ specifier for a function. Admittedly, the compiler can
> ignore such hints.

What _semantic_ difference? There isn't any.

> Therefore, with respect, it is not the red herring you claim.


It most certainly is.

Douglas Boffey

unread,
May 23, 2015, 5:53:52 AM5/23/15
to std-pr...@isocpp.org
As I have already stated (twice), the semantic difference is in
advising the compiler to expand the function inline. Is that too
difficult to understand?

Ville Voutilainen

unread,
May 23, 2015, 5:55:50 AM5/23/15
to std-pr...@isocpp.org
On 23 May 2015 at 12:53, Douglas Boffey <douglas...@gmail.com> wrote:
> As I have already stated (twice), the semantic difference is in
> advising the compiler to expand the function inline. Is that too
> difficult to understand?


Yes, because "adivising the compiler to expand the function inline" is not
a semantic difference.

dgutson .

unread,
May 23, 2015, 9:12:26 AM5/23/15
to std-proposals


El 22/5/2015 12:20, "Douglas Boffey" <douglas...@gmail.com> escribió:
>
> Consider:
>
> template <typename T>
> class Foo {
>   // whatever
> public:
>   void bar();
>   void baz();
>   void another_fn();
>   // ...
> };

FWIW, I think that something similar has been proposed some years ago:

//no namespace version:
namespace class Foo {
void bar() { ... }
void baz() { ... }
}

// templated version:
template <typename T>
namespace class Foo {
void bar() { ... }
void baz() { ... }
...rest of the definitions
}

It was slightly different since blocks are class-specific.
I don't remember what crushed this.

>
> To define the functions, you would have to write:
>
> template <typename T>
> void Foo::bar() { /* ... */ }
>
> template <typename T>
> void Foo::baz() { /* ... */ }
>
> template <typename T>
> void Foo::another_fn() { /* ... */ }
>
> Wouldn’t it be better if we could write:
>
> template <typename T> {
>   void Foo::bar() { /* ... */ }
>   void Foo::baz() { /* ... */ }
>   void Foo::another_fn() { /* ... */ }
> }
>
> Pro:
> - less typing (although that is not the motivating reason)
> - cleaner, clearer syntax, improving maintainability
> - easier to check correctness
>
> What do people think?
>

dgutson .

unread,
May 23, 2015, 9:12:27 AM5/23/15
to std-proposals


El 23/5/2015 10:09, escribió:
>
>
> El 22/5/2015 12:20, "Douglas Boffey" <douglas...@gmail.com> escribió:
> >
> > Consider:
> >
> > template <typename T>
> > class Foo {
> >   // whatever
> > public:
> >   void bar();
> >   void baz();
> >   void another_fn();
> >   // ...
> > };
>
> FWIW, I think that something similar has been proposed some years ago:
>
> //no namespace version:

Errata: "non template version"

Johannes Schaub

unread,
May 23, 2015, 9:27:52 AM5/23/15
to std-pr...@isocpp.org
OK, let's be more serious this time :) I think for what the goal of it
is (avoid repetition of the template header in order to declare member
functions of class templates), this is an overkill-feature on one
side, and too little on another side. I mean, you still have to repeat
the class names, and you open up the gate of declaring anything else
as a template.

I think a more limited and more-to-the-point syntax could be

template<typename T>
class Foo {
void bar();
void baz();
};

template<typename T>
class ::Foo {
// declare the definitions here
void bar() {

}

void baz() {

}
};


Notice the "::Foo", which says "redeclare Foo and zero or more of its
members". If there's a declaration in it that wasn't declared in the
initial definition of the class template, the program is ill-formed.

Douglas Boffey

unread,
May 23, 2015, 9:32:17 AM5/23/15
to std-pr...@isocpp.org
Ok, even if I chose the wrong word, it doesn’t invalidate my point.

Johannes Schaub

unread,
May 23, 2015, 9:43:56 AM5/23/15
to std-pr...@isocpp.org
2015-05-22 17:20 GMT+02:00 Douglas Boffey <douglas...@gmail.com>:
Alternatively, we can introduce "auto" alias templates that will alias
to dependent types:

template<typename T>
auto using T1 = T;

template<typename, typename T>
auto using T2 = T;

Then you write

void Foo<T1>::bar() {

}

void Foo<T2>::bar() {

}

Johannes Schaub

unread,
May 23, 2015, 9:45:00 AM5/23/15
to std-pr...@isocpp.org
Sorry, this should have been

void Foo<T1>::bar() {

}

void Foo<T1>::baz() {

}

Must be too little sleep today

Ville Voutilainen

unread,
May 23, 2015, 10:01:29 AM5/23/15
to std-pr...@isocpp.org
On 23 May 2015 at 16:32, Douglas Boffey <douglas...@gmail.com> wrote:
> Ok, even if I chose the wrong word, it doesn’t invalidate my point.

Your point seems to be at best unsubstantiated and at worst a misconception.
I get the notational convenience of this idea, but I fail to see it
convincing enough
to warrant a language change. Such syntactic sugar would be nice, but I don't
see it as nice enough to change every front-end on the planet to support it.
Reply all
Reply to author
Forward
0 new messages