explicit variable template specialization with external linkage

111 views
Skip to first unread message

templ...@gmail.com

unread,
Oct 16, 2017, 3:28:34 AM10/16/17
to ISO C++ Standard - Discussion
// v.h

extern int const j;
template<int> extern int const i; // a "templated" extern int const

// v.cpp

#include "v.h"
extern int constexpr j = 42;
template<> extern int constexpr i<0> = 666; // error with gcc, but OK with clang

// main.cpp

#include "v.h"
int main()
{
  auto k = j; // 42
  k = i<0>; // 666 with clang
}

This code is fine with clang, but an error with gcc ("explicit template specialization cannot have a storage class"), probably due to 10.1.1 p1 last sentence.

The simple concept behind i is to have a "templated" j.
Of course the template parameters of i could be anything and the type should generally be of literal type so that constexpr in the definition is valid.
I see no reason why this should not be possible.

But 10.1.1 p1 forbids the storage class specifier extern in an explicit template specialization.
So gcc seems to be right, clang seems to be wrong but gets the idea and compiles successfully.

I haven't found a defect report on this, and nothing in this forum.
I have posted this issue on stackoverflow but with no solution so far (https://stackoverflow.com/questions/46752714/erroneous-explicit-template-specialization-of-variable-template-in-gcc).

Just like clang I think this code should be possible.
So I suggest that an exception is made in the afore mentioned sentence for explicit specializations of variable templates declared extern.

Richard Smith

unread,
Oct 16, 2017, 4:19:37 PM10/16/17
to std-dis...@isocpp.org
On 16 October 2017 at 00:28, <templ...@gmail.com> wrote:
// v.h

extern int const j;
template<int> extern int const i; // a "templated" extern int const

// v.cpp

#include "v.h"
extern int constexpr j = 42;
template<> extern int constexpr i<0> = 666; // error with gcc, but OK with clang

// main.cpp

#include "v.h"
int main()
{
  auto k = j; // 42
  k = i<0>; // 666 with clang
}

This code is fine with clang, but an error with gcc ("explicit template specialization cannot have a storage class"), probably due to 10.1.1 p1 last sentence.

The simple concept behind i is to have a "templated" j.
Of course the template parameters of i could be anything and the type should generally be of literal type so that constexpr in the definition is valid.
I see no reason why this should not be possible.

But 10.1.1 p1 forbids the storage class specifier extern in an explicit template specialization.
So gcc seems to be right, clang seems to be wrong but gets the idea and compiles successfully.

I haven't found a defect report on this, and nothing in this forum.

Core issue 1713 seems closely related; per the discussion in that issue, the template "i" and its explicit specializaion should have external linkage regardless of whether "extern" is present, meaning you would be able to write this instead:

template<> int constexpr i<0> = 666;

Sadly not all compilers agree on this at this point.

I have posted this issue on stackoverflow but with no solution so far (https://stackoverflow.com/questions/46752714/erroneous-explicit-template-specialization-of-variable-template-in-gcc).

Just like clang I think this code should be possible.
So I suggest that an exception is made in the afore mentioned sentence for explicit specializations of variable templates declared extern.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+unsubscribe@isocpp.org.
To post to this group, send email to std-dis...@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.

templ...@gmail.com

unread,
Oct 17, 2017, 3:52:57 PM10/17/17
to ISO C++ Standard - Discussion
Thanks for your evaluation.
If extern is dropped in the definition of i<0> (which would be standard conformant considering your reply) both compilers report the error "undefined reference to i<0>" which implies internal linkage of i<0> instead of external linkage.
In short: the behavior of both compilers is non-conformant and qualifies as a bug?
If so I would report this at least for clang.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussio...@isocpp.org.

Richard Smith

unread,
Oct 18, 2017, 8:42:22 PM10/18/17
to std-dis...@isocpp.org
On 17 October 2017 at 12:52, <templ...@gmail.com> wrote:
Thanks for your evaluation.
If extern is dropped in the definition of i<0> (which would be standard conformant considering your reply) both compilers report the error "undefined reference to i<0>" which implies internal linkage of i<0> instead of external linkage.
In short: the behavior of both compilers is non-conformant and qualifies as a bug?
If so I would report this at least for clang.

Yes, given the current direction of that core issue, it seems reasonable to file this as a bug against those compilers.
 
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+unsubscribe@isocpp.org.

templ...@gmail.com

unread,
Oct 19, 2017, 1:30:22 AM10/19/17
to ISO C++ Standard - Discussion
OK, thank you.
Reply all
Reply to author
Forward
0 new messages