[cfe-dev] Warn on template def after explicit instantiation?

Robinson, Paul Paul.Robinson at am.sony.com
Mon Jan 7 09:07:33 PST 2013


From: John McCall [rjmccall at apple.com]
>On Jan 4, 2013, at 5:58 PM, "Robinson, Paul" <Paul.Robinson at am.sony.com> wrote:
>>> On Jan 4, 2013, at 4:44 PM, "Robinson, Paul" <Paul.Robinson at am.sony.com> wrote:
>>>> A client ran into the following situation. Suppose we have this:
>>>>
>>>> // Declarations from a header file.
>>>> template <class T> SomeTemplate {
>>>> public:
>>>>   void Init();
>>>> };
>>>> class FooBar { };
>>>> // End of the header file.
>>>>
>>>> // Here's the initial source module.
>>>> // Explicitly instantiate SomeTemplate.
>>>> template SomeTemplate<FooBar>;
>>>> // Oops, forgot to define Init().
>>>> template <class T> SomeTemplate<T>::Init() { }
>>>> // Now we use the stuff.
>>>> SomeTemplate<FooBar> Obj;
>>>> void foo() {
>>>>   Obj.Init();
>>>> }
>>>>
>>>> This built cleanly. But, moving Obj and foo() to another source file
>>>> caused a link-time error, because of an undefined reference to
>>>> SomeTemplate<FooBar>::Init().  (Call this "version 2.")
>>>>
>>>> The client understands that the original module worked because
>>>> "Obj.Init()" implicitly instantiated SomeTemplate<FooBar>::Init() as a
>>>> definition, because the template definition existed in the same
>>>> compilation unit. And moving the same code to a separate module
>>>> implicitly instantiated Init() as a declaration, because that's all
>>>> that was in the header file.  The "template SomeTemplate<FooBar>;"
>>>> didn't instantiate a definition of Init() because that definition hadn't
>>>> happened yet; hence, the link-time error. The fix was to move the
>>>> explicit instantiation down past the template method definitions.
>>>> (Call that one "version 3.")
>>>>
>>>> His question is: Can we have a warning for the situation where a
>>>> template definition of a method follows an explicit instantiation of
>>>> its containing class?  (Or maybe, if a template definition follows an
>>>> explicit instantiation of its declaration?)  He argues that while it's
>>>> well-defined by the standard, it's probably a mistake on the
>>>> programmer's part (as it was for his code), and a compile-time
>>>> diagnostic would have made it a lot easier to figure out.
>>>
>>> I'd be skeptical of such a warning.  It's certainly reasonable for a
>>> user who's decided to play careful explicit-instantiation games to
>>> be intentionally defining a member after the explicit instantiation
>>> to avoid the instantiation of a particular member.  That makes it
>>> hard to justify this warning being default-on — and I can't
>>> really imagine it doing much good being default-off.
>>
>> It's true that a template-savvy coder could devise something where some
>> methods did not exist for certain specializations.  But...
>> I should think the more common use-case is somebody porting code from
>> MSVC or other less-careful compiler to Clang, and running into this
>> unintentionally.
>>
>> As a parallel example, Clang now complains if I fail to parenthesize
>> expressions with multiple operators where it thinks I might not be
>> getting the precedence right.  This is not exactly expert-friendly
>> either.  I think this is another example in the same vein.
>
> One major difference is that that warning can easily be suppressed
> through innocuous code changes — changes that, in fact, make the
> code more legible to people who haven't memorized the more
> obscure parts of the precedence tables.  There is no way I can see
> to suppress your proposed warning without significantly changing
> the behavior of the code — for example, switching an explicit
> instantiation of a class to an explicit instantiation of every defined
> member of it.
>
> Another major difference is that that warning points out something
> that otherwise requires dynamic testing to detect.  Your warning
> points out something that, if it matters at all, is going to cause the
> build to fail anyway.  We still do like to warn about those things when
> we can, but it does make it a lot less important.

Okay, I can see that.

> A third difference is that I consider (and I think most people would
> agree with me) explicit instantiation of out-of-line definitions of class
> template members to be an expert technique.  That makes it more
> likely that the user really is intending to do something subtle.

But not if you're porting code from a Microsoft environment.
Would a warning in Microsoft compatibility mode be reasonable?

> All that said, it would be reasonable to have a warning about explicit
> instantiations that don't seem to be necessary.  If I had to make a
> none-too-careful first guess at the criteria for such a warning, it would
> be explicit instantiations of class templates that (1) aren't preceded
> by an explicit instantiation declaration and (2) don't instantiate any
> methods that aren't defined in the class definition.  If that would catch
> your user's case, then great.

I can't say I completely followed that, but it doesn't sound like it
matches my user's case.

> John.




More information about the cfe-dev mailing list