Topic: proposal?: template interfaces


Author: llewelly.at@xmission.dot.com (LLeweLLyn)
Date: Mon, 24 Feb 2003 20:10:29 +0000 (UTC)
Raw View
danielgutson@hotmail.com (danielgutson@hotmail.com) writes:
[snip]
> ---Begin brainstorming-mode.
[snip]
> A template condition would cover complex situation validations with
> boolean expressions.
>
> Let me go by steps with an open draft:
>
> first, a [i.e. class] template would look as
>
> template <typename A, typename B, int C> MyCondition?<A,B,C> class
> MyClass
> {
> };
>
> where MyCondition?<> is optional (for compatibility; its absence means
> 'irrestricted', in the same way it is now).
> Many templates could use the same condition.
>
> The condition, would look like:
>
> template_condition < typename A, typename B, int C> MyCondition
> {
>    condition1;
>    ...
>    conditionN;
> };

This is begining to sound like an alternative to SFINAE and template
    specializations. (Which are currently used to construct templates
    that respond to various conditions.)

Again, have a look at the boost concept checks. They will give you a
    better idea both of (a) what can be done in current c++, without
    your proposed feature, and (b) what the use cases of your proposed
    feature might be.

I think this sort of extension can be an improvement in readability,
    but not an improvement in expressiveness. That being said, I *do*
    want the committee's extensions group to consider 'syntactic
    sugar' features that make template meta-programming easier.

Speaking of the comittee, there are lots of papers availible from the
    WG21 website, some of them discussing template and or
    meta-programming related extensions. I haven't checked recently,
    but there may be a proposal or two which has brought up issues
    directly relavent to your ideas.

> where each condition would evaluate to a boolean expression during
> compile time (let me define the operands below).
> The implicit bool. operator is 'AND', so ALL the conditions should be
> accomplished.
>
> Inside each condition, parenthesis, &&, || and ! operators could nest
> subconditions.

Are template conditions allowed inside of template conditions? To me,
    this seems the most natural way to compose new conditions from
    existing conditions.

>
> template_conditions would be able to inherit from other
> template_conditions, including all its conditions in the same 'and'
> fashion.

What does this mean?

>
> The atomic condition would admit:
> 1) inheritance and template inheritance operator ':'
> 2) existance of funtions a global operators
> 3) relational operators for integral template parameters
>
> Deployment:
>
> 1) inheritance.
>      If we want to ensure that a template parameter 'accomplishes' a
> given interface, we could write
>        A:MyInterface
> (and using ',' for multiple inheritance)
> This would be both for template and non-template inheritance. (let's
> say, 'common' inheritance: base-class testing).
[snip]

If I understand what you are suggesting, Stroupstrup explains why it
    is a bad idea (for C++) in D&E 15.4.1

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: danielgutson@hotmail.com (danielgutson@hotmail.com)
Date: Mon, 17 Feb 2003 17:09:30 +0000 (UTC)
Raw View
kuyper@wizard.net (James Kuyper) wrote in message
[snip]
> You can't possibly cover all of the requirements of an arbitrary
> template with any reasonable syntax, but I agree that there could be
[snip]

Ok, this is a general answer, not only for James.

First, I admit you gave me feedback of many situations I didn't think
about.

What I wanted to go, is specifically to 'explicit' parametric
polymorphism, something like

class X : public Y, template Z
{ ... };

where you could mix both kinds (Z would be a template interface).

BUT, with all your comments, I arrive that:
* providing template instantiation preconditions, the compiler would
become an interpreter for testing such conditions.
* 'interface' compliancy is just one case inside many (as many of you
mentioned).

>From this point, I would give this proposal up. What follows is an
invitation for a brainstorming.
Whoever wanting to participate thinking that the intention of the
proposal is important, is welcommed.

---End proposal-mode.

---Begin brainstorming-mode.

The only syntax I can reach, but I'm not sure how acceptable is (in
terms of usefullness, readability, practiceness, etcetcetc), is a new
construct, a template_condition.
A template condition would cover complex situation validations with
boolean expressions.

Let me go by steps with an open draft:

first, a [i.e. class] template would look as

template <typename A, typename B, int C> MyCondition?<A,B,C> class
MyClass
{
};

where MyCondition?<> is optional (for compatibility; its absence means
'irrestricted', in the same way it is now).
Many templates could use the same condition.

The condition, would look like:

template_condition < typename A, typename B, int C> MyCondition
{
   condition1;
   ...
   conditionN;
};

where each condition would evaluate to a boolean expression during
compile time (let me define the operands below).
The implicit bool. operator is 'AND', so ALL the conditions should be
accomplished.

Inside each condition, parenthesis, &&, || and ! operators could nest
subconditions.

template_conditions would be able to inherit from other
template_conditions, including all its conditions in the same 'and'
fashion.

The atomic condition would admit:
1) inheritance and template inheritance operator ':'
2) existance of funtions a global operators
3) relational operators for integral template parameters

Deployment:

1) inheritance.
     If we want to ensure that a template parameter 'accomplishes' a
given interface, we could write
       A:MyInterface
(and using ',' for multiple inheritance)
This would be both for template and non-template inheritance. (let's
say, 'common' inheritance: base-class testing).

2) global functions/operators existance:
     if we want to ensure that a global function accepting the
template_condition parameters exist, we could test
         [rettype] f(A,B,double)
saying that a prototype of 'f' must exist accepting types A and B
(template_condition parameters) and double.
(rettype could also be specified or not; if specified, it could be a
specific type, or a template_condition parameter).

Same thing with operators:
if we want to ensure that an operator (member or non-member) exist
between A and B, we could write
        [rettype] A+B
        [rettype] A<<B

3) relational operators. If C is an integral template_condition
parameter, we could specify conditions on it:
        C > 3

Finally, an example for MyCondition:

template_condition < typename A, typename B, int C> MyCondition:
ABaseCondition
{
   (C>3 && C<10);
   A:MyBase1;
   (B:template MyTemplate2 || B:MyBase2);
   int A+B;
   myFunction(A,B);
};

I think that this would cover a good set of situations.

Is it adiction to complexity?

   Daniel.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: rogero@howzatt.demon.co.uk ("Roger Orr")
Date: Thu, 13 Feb 2003 00:27:40 +0000 (UTC)
Raw View
<danielgutson@hotmail.com> wrote in message
news:23478c42.0302102345.244450c8@posting.google.com...
> Hi people,
>  I have a concern about templates. I will write this in a form of a
> proposal, but maybe I   m the only concerned about this. Please let me
> know.
>
> Overview & motivation:
>  When a class [for example of a library] is a template class, often it
> is not clear what the class will use from the template parameter.
> If you will provide such parameter, I would like to have a way of
>    seeing    what should I implement (before getting infinite complaining
> template instant.errors).

I agree with your analysis that the current situation can lead to hard to
diagnose compiler messages.

Unfortunately the language allows classes with 'flexible' restrictions,
using the fact that, in general, only methods which are used need to be
instantiable.
For example, operator->() in std::auto_ptr is only valid if -> is valid for
the template argument.

I'm not sure how your proposal would work with such classes.

Regards,
Roger Orr.
--
MVP in C++ at www.brainbench.com



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kuyper@wizard.net (James Kuyper)
Date: Thu, 13 Feb 2003 16:41:50 +0000 (UTC)
Raw View
danielgutson@hotmail.com (danielgutson@hotmail.com) wrote in message news:<23478c42.0302120612.6e9a2173@posting.google.com>...
> hyrosen@mail.com (Hyman Rosen) wrote in message news:<1044985656.745750@master.nyc.kbcfp.com>...
> > danielgutson@hotmail.com wrote:
> > > often it is not clear what the class will
> >  > use from the template parameter.
> >
> > The problem is that usage in templates cannot be covered
> > by simple method requirements. For example, if I write
> >
> >      template <typename OS, typename T>
> >      OS &print(OS &os, const T &t)
> >      { return os << t; }
> >
> > what kind of requirements could you give for OS and T
>
> virtual template <typename T> OsInterface
> {
>   OsInterface& operator << (const T& t);
> };

I'm not entirely clear on the notation, but that looks to me like it's
specifying that the applicable operator<<() must be a member function
of OS. Is it in fact intended to prohibit the possibility of using a
non-member function? How about an operator<<() that matches both OS
and T only after implicit type conversion? Koenig lookup?

You can't possibly cover all of the requirements of an arbitrary
template with any reasonable syntax, but I agree that there could be
some value in providing compile-time checking of the ones that can be
specified. However, I'd say that the most reasonable way to specify
the requirements would be to provide a list of example statements that
must be syntactically valid, in order for the template instantiation
to succeed. For most functions, the function body itself would qualify
as that list. Therefore, we already have this feature, as far as
inline functions are concerned. However, there would be some value in
a seperate specification, for several reasons:

1) The requirements specification might be much shorter than the code
itself.

2) The requirements specification would be part of the template
declaration; it would be present even if the template's definition is
exported to a different translation unit.

3) The specification would list the requirements that are intended to
apply, rather than the ones that are actually imposed by the
implementation of the template. This could be useful if the shorter
size of the specification means it's more likely to be correct, which
means it can be used to validate the template's actual implementation.
A compiler could automatically check to see if that implementation
implies any requirements that aren't in the specification, or is
inconsistent with any of the specified ones.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: philippe_mori@hotmail.com ("Philippe Mori")
Date: Thu, 13 Feb 2003 16:47:42 +0000 (UTC)
Raw View
[...]

> >
> > Overview & motivation:
> >  When a class [for example of a library] is a template class, often it
> > is not clear what the class will use from the template parameter.
> > If you will provide such parameter, I would like to have a way of
> >    seeing    what should I implement (before getting infinite complaining
> > template instant.errors).
>
> I agree with your analysis that the current situation can lead to hard to
> diagnose compiler messages.
>
> Unfortunately the language allows classes with 'flexible' restrictions,
> using the fact that, in general, only methods which are used need to be
> instantiable.
> For example, operator->() in std::auto_ptr is only valid if -> is valid
for
> the template argument.
>
> I'm not sure how your proposal would work with such classes.
>
> Regards,
> Roger Orr.

What you should do in such a case is to provide the list of what must be
implemented and not what could be implemented... so the list should then
contains only what is required to be able to start using it (create an
object
and destroy it and maybe for some essential features - for ex. a map would
require to be able to do comparison since a map is most usefull when it
has at least a few items...)

Then, what you would need is the possibility to associate some
constraints with some member functions...

And also there might be a problem with depedencies... In some
situations, we might need to know the definition of a class only
to be able to validate constraints. What should we then do? Force
definition to be visible? Maybe not always!!! Ignore constraints that
cannot be verified (incomplete type)? Verify constraints only when we
have enough information to do it? or when the contraints is actually
used...

Then the approch become less usefull as it will not be done when
desired... Maybe then we should enable to specify when a constraint
should be checked (probably too complicated for the benefit).

And what to do with constraints that may be verified only at link time?
Say that we have a template function that is always specialized for any
type in specific files that are not seen when compiling that translation
unit...  How can the compiler knows that a specilisation would exists?

In other word, if we depends on a template that only have specilized
funnctions (and only the declaration of the generic one), the compiler
may not knows that a specialization exists... What should we do with
the constraints?





---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: llewelly.@@xmission.dot.com (llewelly)
Date: Thu, 13 Feb 2003 17:49:52 +0000 (UTC)
Raw View
danielgutson@hotmail.com (danielgutson@hotmail.com) writes:

> hyrosen@mail.com (Hyman Rosen) wrote in message news:<1044985656.745750@master.nyc.kbcfp.com>...
> > danielgutson@hotmail.com wrote:
> > > often it is not clear what the class will
> >  > use from the template parameter.
> >
> > The problem is that usage in templates cannot be covered
> > by simple method requirements. For example, if I write
> >
> >      template <typename OS, typename T>
> >      OS &print(OS &os, const T &t)
> >      { return os << t; }
> >
> > what kind of requirements could you give for OS and T
>
> virtual template <typename T> OsInterface
> {
>   OsInterface& operator << (const T& t);
> };

Which fails if a non-member operator (often preferable) is supplied
    for OS and T.

>
> template <typename T, typename OS: OsInterface<T> >
>  OS &print(OS &os, const T &t)
>  { return os << t; }
[snip]

I think you should look into the boost concept checks.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: danielgutson@hotmail.com (danielgutson@hotmail.com)
Date: Tue, 11 Feb 2003 17:07:24 +0000 (UTC)
Raw View
Hi people,
 I have a concern about templates. I will write this in a form of a
proposal, but maybe I   m the only concerned about this. Please let me
know.

Overview & motivation:
 When a class [for example of a library] is a template class, often it
is not clear what the class will use from the template parameter.
If you will provide such parameter, I would like to have a way of
   seeing    what should I implement (before getting infinite complaining
template instant.errors).
For example, I (ashamed) admit I have no clear what should I provide
as an allocator :)
The idea is to    ensure    2 things:
1) I have a clear definition about what the template class will
require from the template parameter
2) The template class developer can ensure he is bounding the usage
from the parameters, so changes can be controlled with a common
template-interface.

In other ways, it   s a legalization of parameterized inheritance.

Proposal:

I propose to define the
a) template interface declaration (as    virtual template   , see below)
b) the usage of the template interface

Development:
a) The template interface looks like a class declaration, with
declarations of the methods, attributes and/or typedefs. It would be
declarred as

virtual template class Name
{
   method_declaration1;
   ...
   method_declarationN;

   ...other declarations.
};

This template interfaces will have neither definitions (only
declarations) nor accessibility modifiers (public, protected, ...).
They can inherit from other template interfaces.
They can also have template parameters (i.e., be templates
themselves).

b) the template class.
Template classes will be able to    use    the template interfaces by
adding the    :    operator to their template parameters, combined with
the    +    operators (see below pls.).

Example:

template <class T:I> class MyClass
{
  ...
};

meaning: MyClass will [only] use the declarations of T present in I.
It will also be solved at compile time (right?) instead of linking
time.
So, this provides:
 1. The warranty to the MyClass    user that providing all the
declarations present in I will be enough for MyClass  (and self-doc.)
 2. the MyClass    development can be    bounded    by limiting the usage of
T by I.
 3. Earlier and lighter validations can be done thru forward
declarations

In the case that I is a template interface receiving template
arguments, they can be passed using the <> :

template <class T:I<int> > class MyClass
{
  ...
};

In the case that the template class uses (requires) more than one
template interface for a template parameter, it can specify them thru
the    +    operator:

template <class T:I1+I2 > class MyClass
{
  ...
};

 so the requirements for T are:
     -the declarations of I1
 and
     -the declarations of I1   s base template interface (recursively)
 and
     -the declarations of I2
 and
     -(same recursive of base on I2)

Addendums:
 *The following situation would be valid:
   template <class T1, class T2:I<T1> > class MyClass { ... };

 *The following situation would be meaningless (and avoided?):
   template <class T1, class T2:T1 > class MyClass { ... };

 *[rule] Whenever the template interface is referred within its
declarations, such type will be replaced by the template parameter
type (see example at the bottom)

Compatibility:
 As far as this is a new syntax, both declarations (template
interfaces and template parameters) are invalid in current syntax.
For the current template usage, we can define them as    irrestricted
template parameters   , meaning that no information is provided, and
should be solved during template instantiation in the same way they
are solved now.
(I think that they should become obsolete with this syntax).

A complete example: ------------------(till the end of the message)

A template interface providing an incrementor interface:

virtual template Incrementor
{
   Incrementor& operator ++();
   Incrementor& operator ++(int);
};

A class using it:

template <class I:Incrementor> class X
{
   I i;

public:
   void inc(void)
   {
     i++;      //valid
   }

   void dec(void)
   {
     i--;      //invalid: operator -- not defined in Incrementor
   }
};

void somewhere(void)
{
   X<int> x;    //valid: int has both ++ pre/post operators

   struct MyStruct{};
   X<myStruct> y;     //invalid
}

Thanks!

   Daniel.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Wed, 12 Feb 2003 04:04:31 +0000 (UTC)
Raw View
danielgutson@hotmail.com wrote:
> often it is not clear what the class will
 > use from the template parameter.

The author of the class should document this.

> I have no clear what should I provide as an allocator :)

See 20.4.1.

> In other ways, it=B4s a legalization of parameterized inheritance.

The problem is that usage in templates cannot be covered
by simple method requirements. For example, if I write

     template <typename OS, typename T>
     OS &print(OS &os, const T &t)
     { return os << t; }

what kind of requirements could you give for OS and T
that would cover the various possibilities of member
functions, standalone methods, Koenig lookup, and
automatic conversions that are possible?

Like 'final' and the other restrictive proposals that abound,
all this would have the effect of preventing useful code from
working, because the original writer will have failed to forsee
a use, and will have ruled it out through a restriction.

You can describe template requirements to your users using
words. If clients fail to meet those requirements, the code
won't compile, just as if your proposal was in place.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: danielgutson@hotmail.com (danielgutson@hotmail.com)
Date: Wed, 12 Feb 2003 18:32:30 +0000 (UTC)
Raw View
hyrosen@mail.com (Hyman Rosen) wrote in message news:<1044985656.745750@master.nyc.kbcfp.com>...
> danielgutson@hotmail.com wrote:
> > often it is not clear what the class will
>  > use from the template parameter.
>
> The problem is that usage in templates cannot be covered
> by simple method requirements. For example, if I write
>
>      template <typename OS, typename T>
>      OS &print(OS &os, const T &t)
>      { return os << t; }
>
> what kind of requirements could you give for OS and T

virtual template <typename T> OsInterface
{
  OsInterface& operator << (const T& t);
};

template <typename T, typename OS: OsInterface<T> >
 OS &print(OS &os, const T &t)
 { return os << t; }


Thanks,
 Daniel.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]