Topic: Abstraction layer correctness


Author: Alberto Ganesh Barbati <AlbertoBarbati@libero.it>
Date: Mon, 30 Jan 2006 21:35:32 CST
Raw View
Kaba ha scritto:
> In proposal N1448, they are trying to find a representation for a
> forward declaration of an instance of a template function.

No, they don't. They are just proposing a syntax to inhibit implicit
instantiation. To use their words: 'What is needed is a syntax to say
"do not implicitly instantiate this specialization here"'. I would add
"do not implicitly instantiate this specialization here, *even if* I
already gave you a definition". Because if you don't give the compiler
the template definitions there would be no need to inhibit the
specialization! It could not happen in the first place! More on this
topic below.

> Ok, here is what I mean by the "better" method:
>
> N1448: Template code must be visible to the plug-in user, even if the
> code has already been instantiated elsewhere and only a few
> instantiations are used

Not true. As the example that you snipped shows, the template code need
not be visible in order for the "extern" syntax to work. However, when
there's no template code, the "extern" declaration is redundant as the
instantiation cannot even take place.

The more I think of your proposal, the more I get convinced that what
you seek is *already* in the language. If you don't want the user to
instantiate a template, just feed him with the declarations only. The
library programmer, who has access to the definitions also, will then
explicitly instantiate the right templates and the linker will do the
rest. What more do you need?

Ganesh

---
[ 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: none@here.com (Kaba)
Date: Tue, 31 Jan 2006 19:21:28 GMT
Raw View
In article <toxDf.153456$65.4310685@twister1.libero.it>,
AlbertoBarbati@libero.it says...
> Kaba ha scritto:
> > In proposal N1448, they are trying to find a representation for a
> > forward declaration of an instance of a template function.
>
> No, they don't. They are just proposing a syntax to inhibit implicit

Yes they do. In the beginning of chapter 2:

This is the specific link I am using:
http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1448.pdf

"Usually, a forward declaration helps to break circular name use
dependencies. For ordinary function, it takes the form
int foo(int);
So, one might think that just putting the template keyword in front of
a forward-declaration might express a ?forward declaration of a function
template specialization?, but it does not; the reason is that the
declaration
template int bar(int);
is the syntax to request an explicit instantiation, not that of a mere
declaration." (and continues further..)

> instantiation. To use their words: 'What is needed is a syntax to say
> "do not implicitly instantiate this specialization here"'. I would add
> "do not implicitly instantiate this specialization here, *even if* I
> already gave you a definition". Because if you don't give the compiler
> the template definitions there would be no need to inhibit the
> specialization! It could not happen in the first place! More on this
> topic below.

Exactly. It is my point that by writing the templates in a specific way
we are able to cut down compilation times and avoid the use of "extern"
extension.

>
> > Ok, here is what I mean by the "better" method:
> >
> > N1448: Template code must be visible to the plug-in user, even if the
> > code has already been instantiated elsewhere and only a few
> > instantiations are used
>
> Not true. As the example that you snipped shows, the template code need
> not be visible in order for the "extern" syntax to work. However, when
> there's no template code, the "extern" declaration is redundant as the
> instantiation cannot even take place.

You are right. I was assuming that if the "extern" is used then the
definition is also given, otherwise the "extern" would have no use,
which is the point of my proposal.

> The more I think of your proposal, the more I get convinced that what
> you seek is *already* in the language. If you don't want the user to

It _is_ in the language, since this is a plain library extension. My
point is that there is a way to write a template that improves compile
speed and works properly with dlls. My second point is that the other
ways to write templates have disadvantages.

> instantiate a template, just feed him with the declarations only. The
> library programmer, who has access to the definitions also, will then
> explicitly instantiate the right templates and the linker will do the
> rest. What more do you need?

I, as a library programmer will do just that. But that does not change
the problem with the STL (and other libraries) which are not on my hands
(and that is what I propose to change). Let's see:

Given the current STL and the header <set>, how do you avoid the
inclusion of great many lines of implementation when all you need is the
interface? You don't.

Does it not bother you that some much implementation code that is not
actually needed is inserted? It does bother me and surely is not
elegant.

You must have noticed that you cannot (portably) forward declare any of
the STL:s classes. Class definition is the next light-weight step up of
that.

It is the style of how templates are written in STL that forces us to
turn to hacks such as the "extern" extension. The hints should be clear
when we are including implementation code and just after that ignoring
it.

As you turn more sure that this technique is not something to consider,
I do not. I am not pursuing this idea just for the fun of writing. The
idea is the result of a few years on thinking about this problem. As
such, I do not expect everybody to grasp on the idea in a couple of
days. To show that the idea is flawed, you have to be concrete on your
reasons and convince me on your view, as I do the same for you. There
might always be some wrong assumption in both of our thinking.

--
Kalle Rutanen
http://kaba.hilvi.org

---
[ 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: none@here.com (Kaba)
Date: Thu, 2 Feb 2006 05:36:07 GMT
Raw View
To make the conversation more concrete, I'll supress the whole
conversation to the following:

Enumerate the template writing strategies. What advantages/disadvantages
are there in each? Are they all equivalent (roughly, excluding for
example inlining etc)?

By this we should be able to compare the style used in stl to other
styles, and make a decision.

You can add your own, I'll enumerate some of them by giving an example
of each (I'll omit include guards):

1) In-class function definitions

mytemplate.h
------------

template <typename T>
class MyTemplate
{
public:
void f()
{
a_= 3;
}
private:
int a_;
};

2) Out-of-class function definitions

mytemplate.h
------------

template <typename T>
class MyTemplate
{
public:
void f();
private:
int a_;
};

template <typename T>
void MyTemplate<T>::f()
{
a_ = 3;
}

3) Out-of-class functions definition, physically separated

mytemplate.h
------------

template <typename T>
class MyTemplate
{
public:
void f();
private:
int a_;
};

#include "mytemplate.inl"

mytemplate.inl
--------------

template <typename T>
void MyTemplate<T>::f()
{
a_ = 3;
}

4) Export

mytemplate.h
------------

export template <typename T>
class MyTemplate
{
public:
void f();
private:
int a_;
};

mytemplate.cpp
--------------

#include "mytemplate.h"

template <typename T>
void MyTemplate<T>::f()
{
a_ = 3;
}

5) Out-of-class functions definitions, separated physically and
logically (note similarity to export example)

mytemplate.h
------------

template <typename T>
class MyTemplate
{
public:
void f();
private:
int a_;
};

mytemplate.hpp
--------------

#include "mytemplate.h"

template <typename T>
void MyTemplate<T>::f()
{
a_ = 3;
}

1,2 and 3:
1,2 and 3 are roughly equivalent.

5 to (1,2,3):
Number 5 is not equivalent to 1,2 and 3. It can do all they can do and
more: it can supply only the class definition when needed. It can also
avoid code exposition, when the specific instances are explicitly
instantiated in advance. It is therefore more general than 1,2, and 3.

5 to 4:
When using mytemplate.hpp, it is able to do anything that number 4
(export), but must supply the function definitions (and this is a
natural requirement). Therefore number 5 is not as generic as number 4.
But we know the difficulties with export.

Now consider, in what numbers are the stl classes forced to be? The
answer is: 1,2,3 and 4. While the export keyword could be the most
generic option, in practice its generity goes too far (in my opinion)
and the option 5 strikes the right balance between advantages and
disadvantages.

In a consequence, there is no large support for export, and the
practically used techniques are 1,2 and 3. But these techniques cause
the problems with compile times and dlls!

Hope this makes my concern more specific.

--
Kalle Rutanen
http://kaba.hilvi.org

---
[ 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: none@here.com (Kaba)
Date: Thu, 26 Jan 2006 22:52:19 GMT
Raw View
Hello

This is an informal proposal (meant to raise conversation) to separate
the template definitions from their implementation in STL. Currently the
inclusion of (for example) <set> results in both the class definition
and implementation given. This creates a dependency between the two. I'd
like to show that this leads to problems, but can be corrected in a
simple way.

This is also in connection with the proposal N1448, which asks for a way
to restrict instantiation of a template. Also connected is the extension
to the C++ implemented in many compilers, which is the "extern" of
explicit template instantiations.

I call the problem "abstraction layer incorrectness" and I describe it
more wordily here:

http://kaba.hilvi.org/project/abstraction/index.htm

By the argumentation of the former document, I propose to add (for
example) <set_def> to match <set>, which gives only the template class
definition of set and multiset and by definition <set> should include
<set_def>. As a consequence, we are able to cut down compile times and
combine stl with dlls properly.

Enough writing.. Opinions, please?

--
Kalle Rutanen
http://kaba.hilvi.org

---
[ 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: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Sat, 28 Jan 2006 07:16:12 GMT
Raw View
Kaba ha scritto:
> Hello
>
> This is an informal proposal (meant to raise conversation) to separate
> the template definitions from their implementation in STL. Currently the
> inclusion of (for example) <set> results in both the class definition
> and implementation given. This creates a dependency between the two. I'd
> like to show that this leads to problems, but can be corrected in a
> simple way.
>
> This is also in connection with the proposal N1448, which asks for a way
> to restrict instantiation of a template. Also connected is the extension
> to the C++ implemented in many compilers, which is the "extern" of
> explicit template instantiations.
>
> I call the problem "abstraction layer incorrectness" and I describe it
> more wordily here:
>
> http://kaba.hilvi.org/project/abstraction/index.htm
>
> By the argumentation of the former document, I propose to add (for
> example) <set_def> to match <set>, which gives only the template class
> definition of set and multiset and by definition <set> should include
> <set_def>. As a consequence, we are able to cut down compile times and
> combine stl with dlls properly.
>
> Enough writing.. Opinions, please?
>

I admit that I did not read the full article, yet I feel the urge to ask
you a few questions that I sense essential to set up a solid base for
the incoming discussion:

1) since neither your post nor your article mentions the "export"
keyword, a thing that I would have expected, are you aware of its
existence and the fact that it aims at solving a similar issue?

2) are you aware of the issues raised by the feat of implementing
"export" (separate compilation, two phase name binding, etc.)?

3) how is your proposal different from "export", which is *already* a
standard feature, albeit implemented by very few compilers?

Ganesh

---
[ 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: Kaba <none@here.com>
Date: Sat, 28 Jan 2006 11:25:44 CST
Raw View
> 1) since neither your post nor your article mentions the "export"
> keyword, a thing that I would have expected, are you aware of its
> existence and the fact that it aims at solving a similar issue?
>
> 2) are you aware of the issues raised by the feat of implementing
> "export" (separate compilation, two phase name binding, etc.)?
>
> 3) how is your proposal different from "export", which is *already* a
> standard feature, albeit implemented by very few compilers?

Hello Ganesh, thanks for starting the conversation.

Yes, I am aware of "export" and the difficulty of implementing it.

http://www.gotw.ca/publications/mill23.htm

However my proposal is different from "export". Export tries to fully
separate function definitions from the declarations and still be able to
generate _any_ template. Given that, I think it is then obvious that the
template source code can't then be logically separated from the
declaration.

What I propose is that there is a way to choose between including the
declaration and the declaration with definition. If a template function
is used in a source code and is not given a definition then it is
assumed that the instantiation relies in a different translation unit
(extern). If in the linking phase the instantiation is not found, an
error is generated.

The difference is that export claims to be able to generate any template
instantiation that is not defined yet, while my proposal claims to be
able to say that the template instantiation relies in a different
translation unit.

Let's see: When developing a plug-in based application you want to give
the plug-in developer a set of functions and classes which he can use to
carry out the task he wants to. Naturally, to keep the code in one place
and to keep the plug-ins small, you instantiate the needed template
instantiations in your (dynamic) library. By not giving the plug-in
developer the template implementation you are saying the compiler "the
implementation, if exists, relies in a different translation unit". When
the plug-in developer links with your library, all is resolved (given
that he uses only the template instantiations you have instantiated).

To make this conversation more concrete, we can shorten it to code
(omitting include guards):

START EXAMPLE

// set.h

template <typename T>
class Set
{
public:
    void f();
private:
    int a_;
};

// set.hpp

#include "set.h"

template <typename T>
void Set<T>::f()
{
    a_ = 4;
}

// plugin.cpp

#include "set.h"

void myPluginFunction()
{
    Set<int> a;
    a.f();
}

// application.cpp

#include "set.hpp"
int main()
{
    return 0;
}

// Explicitly instantiate, place to the dllexport table
template class __declspec(dllexport) Set<int>;

END EXAMPLE

While this is non-standard code (__declspec(dllexport)), it is only to
make a point, since dlls is the techniques most motivating target.

We can actually talk in terms of this code. Can you see any problems
with its use and why it should not work (in terms of the standard, it
does work with for example msvc 8.0)?

--
Kalle Rutanen
http://kaba.hilvi.org

---
[ 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: Alberto Ganesh Barbati <AlbertoBarbati@libero.it>
Date: Sat, 28 Jan 2006 18:58:26 CST
Raw View
Kaba ha scritto:
> The difference is that export claims to be able to generate any template
> instantiation that is not defined yet, while my proposal claims to be
> able to say that the template instantiation relies in a different
> translation unit.

Ok, so it seems that your proposal is actually more similar to "extern"
proposal N1448 than to some kind of "export" feature. Let me see if I
understood it well by enumerating the main differences between the two
proposals:

N1448: the programmer can use a new syntax ("extern template") to
inhibit implicit instantiation of a particular specialization of a
template, effectively forcing the compiler to assume that an
instantiation will be provided by some other translation unit.

Yours: if a template would need to be implicitly instantiated but no
definition has yet been provided, the compiler shall not produce an
error (as it is now) but shall assume that an instantiation will be
provided by some other translation unit.

(by "template" I mean a function template or a member template, because
a class template must always be defined in order to be used as a
concrete type).

Is my understanding right?

> We can actually talk in terms of this code. Can you see any problems
> with its use and why it should not work (in terms of the standard, it
> does work with for example msvc 8.0)?

I don't see any problems with *that* code, but your proposal would
impact some programming idioms that rely precisely on the attempt to
instantiate a template for which no definition has been provided (for
example BOOST_STATIC_ASSERT). Your proposal would defer the error from
compile-time to link-time, possibly with a loss in usefulness due the
different diagnostic. I understand that this is not a very compelling
argument... the code is ill-formed anyway so the standard is not
required to well-behave, but a lot people (including myself) won't be happy.

Anyway, from certain sentences in your article, I got the impression
that your bad opinions about N1448 are due to a misunderstanding of that
proposal. For instance, you wrote:

--After considering this, you start to see that the "extern" extension
and the proposal N1448 are just attempts to repair something that was
damaged in the start. That is, they say "I want to include class
definition and its implementation and then get rid of the
implementation". This is equivalent to saying "I just want the class
definition, not the implementation".---

I don't see it that way. Your opinion is biased by the example given in
N1448, which essentially is:

---- MyVector.h
template <class T> class MyVector
{
  /* implementation here */
};

---- Main.cpp
// include declaration and implementation
#include "MyVector.h"

// inhibit instantiation, effectively getting rid of
// the implementation which we already have!
extern template class MyVector<int>;

int main() { /* use MyVector<int> */ }
----

but if you read the proposal more creatively, it also allows this use-case:

---- MyVector.h
template <class T> class MyVector
{
  /* only declaration, NO implementation here */
};

// inhibit implicit instantiation, effectively *declaring* that
// this instantiation is provided elsewhere
extern template class MyVector<int>;

---- MyVector.cpp
#include "MyVector.h"

/* out of class implementation here */

template class MyVector<int>; // explicit instantiation

---- Main.cpp
// include declaration only
#include "MyVector.h"

int main() { /* use MyVector<int> */ }
----

Isn't that very similar to your code? The only difference is that the
compiler knows exactly (at compile-time!) which specializations it can
expect to find instantiated and which don't, something that your
proposal doesn't provide.

I wrote too much... now it's your turn ;-)

Ganesh

---
[ 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: none@here.com (Kaba)
Date: Sun, 29 Jan 2006 19:11:02 GMT
Raw View
> Ok, so it seems that your proposal is actually more similar to "extern"
> proposal N1448 than to some kind of "export" feature. Let me see if I
> understood it well by enumerating the main differences between the two
> proposals:

Exactly, I am after the same thing as N1448. By this conversation I aim
to find out if my proposal has any flaws. If it does not have, then we
have a better method than N1448 without requiring a language extension.
I'll reason what I mean by "better" below.

> N1448: the programmer can use a new syntax ("extern template") to
> inhibit implicit instantiation of a particular specialization of a
> template, effectively forcing the compiler to assume that an
> instantiation will be provided by some other translation unit.
>
> Yours: if a template would need to be implicitly instantiated but no
> definition has yet been provided, the compiler shall not produce an
> error (as it is now) but shall assume that an instantiation will be
> provided by some other translation unit.
>
> (by "template" I mean a function template or a member template, because
> a class template must always be defined in order to be used as a
> concrete type).
>
> Is my understanding right?

Right, except for one thing. I don't see any reason why the compiler
should produce an error if the function definition is missing, which is
one thing I'd like to have an ensure to from you. My view is backed by
two compilers msvc80 and comeau.

http://www.comeaucomputing.com/tryitout/

In proposal N1448, they are trying to find a representation for a
forward declaration of an instance of a template function. They claim
there is no such thing. But consider:

template <typename T>
void f();

I view this as a family of forward declarations for all possible
instantiations in parallel.

> I don't see any problems with *that* code, but your proposal would
> impact some programming idioms that rely precisely on the attempt to
> instantiate a template for which no definition has been provided (for
> example BOOST_STATIC_ASSERT). Your proposal would defer the error from
> compile-time to link-time, possibly with a loss in usefulness due the
> different diagnostic. I understand that this is not a very compelling
> argument... the code is ill-formed anyway so the standard is not
> required to well-behave, but a lot people (including myself) won't be happy.

I guess you are referring to the usefulness of incomplete instantiation.
I am not taking that away. You are probably thinking of the explicit
instantiation I am making to be able to dllexport the code. But in
normal non-dll code you do not need to do the explicit instantiation.

And further, for those templates that rely on incomplete instantiation,
you can rely on member-by-member dllexport.

Whether the code is ill-formed needs more thinking.. Can you give a
reasoning from the standard?

> Anyway, from certain sentences in your article, I got the impression
> that your bad opinions about N1448 are due to a misunderstanding of that
> proposal. For instance, you wrote:

To ensure I understand it, I reread with good attention.

Ok, here is what I mean by the "better" method:

N1448: Template code must be visible to the plug-in user, even if the
code has already been instantiated elsewhere and only a few
instantiations are used
Mine: Template code can be visible if the system programmer so chooses,
normally you would of course keep the code yourself to ensure that you
can update your system without needing to recompile the plug-ins.
Anyway, all is in the hands of the system programmer.

N1448: It is easy to forget to "externalize" the specific instance.
"extern" only externalizes one instance, not all.
Mine: Without template source it is not possible to generate any code.

N1448: a language extension
Mine: a library extension

I still think N1448 is a method to revert something that shouldn't have
happened in the first place.

Now is your turn;)

--
Kalle Rutanen
http://kaba.hilvi.org

---
[ 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                       ]