Greetings.

Signature
--Larry Brasfield
email: donotspam_larry_brasfield@hotmail.com
Above views may belong only to me.
> First, the 'inline' keyword is strictly an advisory to the
> compiler. There is no requirement in the C++ standard
> that the compiler inline whatever is so marked, nor is
> the compiler precluded from inlining code not so marked.
Yes, I know. However, you're missing the point! Semantically, the
following
two are equivalent (see C++ standard: 7.1.2-3, 9.3-2, and 9.3-3):
template<typename T>
class Foo
{
public:
T foo(void) const
{
return m_value;
}
T m_value;
};
template<typename T>
class Foo
{
public:
T foo(void) const;
T m_value;
};
template<typename T>
inline T Foo<T>::foo(void) const
{
return m_value;
}
The fact that the VC compiler treats them differently in some cases must be
considered a bug.
> One might make an argument (albeit a complex one)
> that this is a quality of implementation issue. I will
> take the side of the compiler implementers on this one.
Why? If you are taking the side of the implementer, you have to believe
that there is a rationale for treating these two cases differently. This
not
only violates the C++ standard but also the principle of least surprise.
> Why would you use a DLL if it was not supposed to
> be interchangable with newer versions or (in the case
[quoted text clipped - 5 lines]
> implementation, and bind the two at nearly the latest
> possible moment.
You are jumping to conclusions from the fact that I had to make a very
simple
example (which you then even find not basic enough) to showcase the problem.
Yes, in this simplistic example, using a DLL is of course overkill.
The problem is that from what I've seen, even if the template is declared in
a separate header file or a static lib, as soon as some class declared with
__declspec(dllimport) derives from that template, the template itself is
instantiated with __declspec(dllimport) and all its member functions are
exported by the DLL. If the writer of that template didn't put the
implementations of the member functions in the class body, they will never
be
inlined due to this bug.
> If you cannot get happy with it, I would suggest that
> a few friends with whatever privileged access those
> would-be inlined methods enjoyed could be made
> to accomplish the same effect. That approach will
> degrade encapsulation somewhat, but that clearly
> is something you are willing to tolerate.
That doesn't make any sense at all. It is akin to saying: "that bug is not
really a bug because there is a workaround for it". As it were, there is
actually a much simpler workaround: put the implementation of the member
functions into the class body. However, that of course only works for code
one has control over (as opposed to third party libraries). Even then,
having to go back and identify cases where it makes sense to move the
implemenation into the body it existing code is rather tedious and error
prone.
--Felix
Larry Brasfield - 16 Mar 2005 02:13 GMT
>> First, the 'inline' keyword is strictly an advisory to the
>> compiler. There is no requirement in the C++ standard
>> that the compiler inline whatever is so marked, nor is
>> the compiler precluded from inlining code not so marked.
>
> Yes, I know. However, you're missing the point!
That point is central to the "bug?" issue. I will try,
however, to comprehend your other points, as I
did initially (subject to code reading hesitation).
> Semantically, the following
> two are equivalent (see C++ standard: 7.1.2-3, 9.3-2, and 9.3-3):
[quoted text clipped - 23 lines]
> return m_value;
> }
Semantically, the inline keyword is invisible unless
it appears in (quite a few) disallowed places.
> The fact that the VC compiler treats them differently in some cases must be
> considered a bug.
I disagree. Within the latitude granted by the C++ standard
as to when inlining must or must not occur, choices that fall
inside the allowed bounds cannot properly be called bugs.
>> One might make an argument (albeit a complex one)
>> that this is a quality of implementation issue. I will
[quoted text clipped - 3 lines]
> that there is a rationale for treating these two cases differently. This not only violates the C++ standard but also the
> principle of least surprise.
I deny that it violates the C++ standard. As for the
principle of least surprise, I will grant that you have
a point, but even that is not a given because surprise
occurs in the mind according to its expectations, a
highly variable set. (I've seen no surprise quantifiers!)
>> Why would you use a DLL if it was not supposed to
>> be interchangable with newer versions or (in the case
[quoted text clipped - 9 lines]
> to showcase
> the problem.
If you claim that problem cannot be demonstrated
with significantly less code, I will not gainsay you.
> Yes, in this simplistic example, using a DLL is of course overkill.
But is not the use of constructs related to DLL creation
at the core of this problem? If not, I misunderstood you.
> The problem is that from what I've seen, even if the template is declared in
> a separate header file or a static lib, as soon as some class declared with
> __declspec(dllimport) derives from that template, the template itself is
> instantiated with __declspec(dllimport) and all its member functions are
> exported by the DLL. If the writer of that template didn't put the
> implementations of the member functions in the class body, they will never be inlined due to this bug.
I can only draw one new fact from that. The rest
appears to repeat your original statement. From
the above, I think you may not know quite where
template code resides before becoming translated
to a concrete, executable form. (But that is a side
issue, I think.)
>> If you cannot get happy with it, I would suggest that
>> a few friends with whatever privileged access those
[quoted text clipped - 5 lines]
> That doesn't make any sense at all. It is akin to saying: "that bug is not
> really a bug because there is a workaround for it".
Well, that might be one interpretation. But what I was
trying to do is provide you a way to deal with the tools
you have, as they are, and get what you want. If you
want to treat it as part of my "not a bug" contention,
please just drop that element because it provides very
poor, pathetic support for that position.
> As it were, there is
> actually a much simpler workaround: put the implementation of the member
> functions into the class body.
I realize that now. Maybe that is the syntax I was
mentioning. And that would be surprising. Maybe
it should be considered a doc bug.
> However, that of course only works for code
> one has control over (as opposed to third party libraries). Even then,
> having to go back and identify cases where it makes sense to move the
> implemenation into the body it existing code is rather tedious and error prone.
Well, inlined members for stuff in a DLL are
error prone. Maybe that tedium acts as a
beneficial barrier.

Signature
--Larry Brasfield
email: donotspam_larry_brasfield@hotmail.com
Above views may belong only to me.
Carl Daniel [VC++ MVP] - 16 Mar 2005 02:16 GMT
>> First, the 'inline' keyword is strictly an advisory to the
>> compiler. There is no requirement in the C++ standard
[quoted text clipped - 4 lines]
> following
> two are equivalent (see C++ standard: 7.1.2-3, 9.3-2, and 9.3-3):
Actually, I don't believe that they are. If the function wasn't originally
introduced with the inline keyword the compiler is free to ignore any
subsequent request to inline it.
> template<typename T>
> class Foo
[quoted text clipped - 12 lines]
> public:
> T foo(void) const;
Change this to
inline T foo() const;
and your assertion that they're the same is correct, but...
> T m_value;
> };
[quoted text clipped - 7 lines]
> The fact that the VC compiler treats them differently in some cases
> must be considered a bug.
I don't think so. Whether a function is inlined or not is not observable
behavior according to the C++ standard, so the compiler's free to inline or
not at its sole discretion - including never inliing or always inlining or
inlining only functions that contain an odd number of source tokens (or
functions
I'll admit it's quirky, and perhaps unexpected, but I don't think it can be
classified as a compiler bug.
-cd
Felix I. Wyss - 16 Mar 2005 03:53 GMT
> Actually, I don't believe that they are. If the function wasn't
> originally introduced with the inline keyword the compiler is free to
> ignore any subsequent request to inline it.
I'm sorry, but you're wrong. From the standard:
9.3-2
"A member function may be defined (8.4) in its class definition,
in which case it is an inline member function (7.1.2), [...]"
I think you're confusing it with this one:
9.3-3
"An inline member function [...] may also be defined outside of its
class definition provided either its declaration in the class
definition or its definition outside of the class definition declares
the function as inline."
> Change this to
>
> inline T foo() const;
Doesn't matter, see above. At any rate, this has no bearing on the issue
at hand anyway. After all, VC *does* inline the member functions if they
are implemented in the template class body (without the "inline" qualifier).
It doesn't inline them if they are defined outside the template class body
with the "inline" qualifier.
>> The fact that the VC compiler treats them differently in some cases
>> must be considered a bug.
[quoted text clipped - 7 lines]
> I'll admit it's quirky, and perhaps unexpected, but I don't think it can
> be classified as a compiler bug.
Well, that may be technically true, but I consider arbitrarily generating
poor
code for, according to the standard, semantically equivalent language
constructs a bug -- or at least a very dubious "feature" that should be
fixed.
--Felix