Allowed to use C++11 extern templates?

500 views
Skip to first unread message

Matthew Dempsky

unread,
Oct 1, 2014, 6:14:08 PM10/1/14
to Chromium-dev
I don't see C++11 extern templates listed anywhere on chromium-cpp.appspot.com.  Are we allowed to use them?  Do we need a formal proposal/discussion thread for them?  (Note: "extern templates" are different than "export templates".)


Brief explanation: C++11 extern templates allow you to suppress automatic instantiation of templates by the compiler.  E.g., you can have something like:

  max.h:
    template <typename T> T Max(T a, T b) { return (a > b) ? a : b; }
    extern template int Max(int, int);
    extern template long Max(long, long);

  max.cc:
    #include "max.h"
    template int Max(int, int);
    template long Max(long, long);

Normally if the compiler sees a call to "Max(int, int)" within a compilation unit, it would have to instantiate the template and emit a compiled copy, which the linker is then responsible for duplicate merging.  However, if it sees the "extern template" declaration above, it can assume there will be an explicit instantiation in some compilation unit, and can avoid the extra work.

This functionality can be used for templates that have very common instantiations; e.g., libstdc++'s <string> includes "extern template class basic_string<char>;" and "extern template class basic_string<wchar_t>;" because std::string and std::wstring are the most common instantiations of basic_string.


Another use is for hiding unnecessary implementation details.  E.g., in sandbox/linux/bpf_dsl, I use the convention of

    namespace internal {
    class FooImpl : base::RefCounted<FooImpl> { ... };
    }
    typedef scoped_refptr<const internal::FooImpl> Foo;

and the user facing APIs are focused around passing around Foos as opaque values.  However, I currently still need to include the FooImpl definition in the header, even though it's a purely implementation detail.

Using extern templates I could change this to:

    namespace internal {
    class FooImpl;
    extern template class scoped_refptr<const FooImpl>;
    }
    typedef scoped_refptr<const internal::FooImpl> Foo;

and keep FooImpl's definition hidden from end users.  (Technically a few of scoped_refptr's member function definitions would need to be moved out-of-line too.)

Nico Weber

unread,
Oct 1, 2014, 6:22:36 PM10/1/14
to Matthew Dempsky, Chromium-dev
Does it work in MSVS now? We have a bunch of places where we use this with gcc and clang but not msvs, 'cause this used to not work there. I don't remember if this was due to the feature not working or due to symbol visibility working differently (see https://code.google.com/p/chromium/codesearch#search/&q=%22extern%20template%22&sq=package:chromium&type=cs for examples – can you try making e.g. the logging.h instantiations extern unconditionally?).

--
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev

Matthew Dempsky

unread,
Oct 1, 2014, 6:29:49 PM10/1/14
to Nico Weber, Chromium-dev
On Wed, Oct 1, 2014 at 3:22 PM, Nico Weber <tha...@chromium.org> wrote:
Does it work in MSVS now?

Not sure.  According to http://msdn.microsoft.com/en-us/library/by56e477.aspx it works in MSVC 2013.

We have a bunch of places where we use this with gcc and clang but not msvs, 'cause this used to not work there. I don't remember if this was due to the feature not working or due to symbol visibility working differently (see https://code.google.com/p/chromium/codesearch#search/&q=%22extern%20template%22&sq=package:chromium&type=cs for examples – can you try making e.g. the logging.h instantiations extern unconditionally?).

I'll prepare a test CL and see what the trybots say.

Matthew Dempsky

unread,
Oct 1, 2014, 9:53:24 PM10/1/14
to Nico Weber, Chromium-dev
On Wed, Oct 1, 2014 at 3:28 PM, Matthew Dempsky <mdem...@chromium.org> wrote:
I'll prepare a test CL and see what the trybots say.

https://codereview.chromium.org/613273005/ failed on one Windows bot, but not obviously *because* of the change.

Do the Windows bots use component builds? If not, perhaps someone (i.e., not me) could locally test that too?

Gabriel Charette

unread,
Oct 1, 2014, 10:39:50 PM10/1/14
to Matthew Dempsky, Nico Weber, Chromium-dev
On Wed, Oct 1, 2014 at 9:52 PM, Matthew Dempsky <mdem...@chromium.org> wrote:
On Wed, Oct 1, 2014 at 3:28 PM, Matthew Dempsky <mdem...@chromium.org> wrote:
I'll prepare a test CL and see what the trybots say.

https://codereview.chromium.org/613273005/ failed on one Windows bot, but not obviously *because* of the change.

Do the Windows bots use component builds?

From the gclient_runhooks step of this particular bot: component=static_library => not a component build. But some bots definitely run the component build AFAIK.

Either way, this failure looks like a flake to me, not a compile error or bad build issue.

 
If not, perhaps someone (i.e., not me) could locally test that too?

--

Matthew Dempsky

unread,
Oct 3, 2014, 1:00:51 PM10/3/14
to Nico Weber, Chromium-dev
On Wed, Oct 1, 2014 at 6:52 PM, Matthew Dempsky <mdem...@chromium.org> wrote:
https://codereview.chromium.org/613273005/ failed on one Windows bot, but not obviously *because* of the change.

CQ and waterfall both look happy with this CL.  What are the next steps here?  Wait longer for more fallout?  Try removing more !defined(COMPILER_MSVC) checks around "extern template" declarations?

Matthew Dempsky

unread,
Oct 6, 2014, 4:13:12 PM10/6/14
to Chromium-dev
On Fri, Oct 3, 2014 at 9:59 AM, Matthew Dempsky <mdem...@chromium.org> wrote:
Try removing more !defined(COMPILER_MSVC) checks around "extern template" declarations?

This has revealed that MSVC still has some quirks around "extern template class" that don't show up with extern template functions.  If anyone clueful about dll{export,import} semantics can help investigate a better workaround, please see crbug.com/420695.
Reply all
Reply to author
Forward
0 new messages