Variable templates with const-qualified types should not default to internal linkage. https://cplusplus.github.io/CWG/issues/2387.html
*** Bug 116077 has been marked as a duplicate of this bug. ***
.
Created attachment 58858 [details] gcc15-pr109126.patch Untested implementation.
The master branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>: https://gcc.gnu.org/g:82cd63a63eaa61a4ed5c4029a1869be7446ecb3c commit r15-2798-g82cd63a63eaa61a4ed5c4029a1869be7446ecb3c Author: Jakub Jelinek <jakub@redhat.com> Date: Wed Aug 7 19:08:07 2024 +0200 c++: Implement CWG2387 - Linkage of const-qualified variable template [PR109126] The following patch attempts to implement DR2387 by making variable templates including their specialization TREE_PUBLIC when at file scope and they don't have static storage class. 2024-08-07 Jakub Jelinek <jakub@redhat.com> PR c++/109126 * decl.cc (grokvardecl): Implement CWG 2387 - Linkage of const-qualified variable template. Set TREE_PUBLIC on variable templates with const qualified types unless static is present. * g++.dg/DRs/dr2387.C: New test. * g++.dg/DRs/dr2387-aux.cc: New file.
Implemented for 15.1+.
It looks like explicit specializations are not given vague linkage. Is that the correct behaviour? /usr/bin/ld: /tmp/ccjbP7xI.o:/tmp/t.h:2: multiple definition of `var<int>'; /tmp/ccMCRAVO.o:/tmp/t.h:2: first defined here Given these two TUs: template<typename T> constexpr bool var = true; template<> constexpr bool var<int> = false; bool foo(); int main() { return var<int> != foo(); } template<typename T> constexpr bool var = true; template<> constexpr bool var<int> = false; bool foo() { return var<int>; } It works if I add 'inline' to the explicit specialization.
(In reply to Jonathan Wakely from comment #6) > It looks like explicit specializations are not given vague linkage. Is that > the correct behaviour? I wonder if that is related to PR 116746 .
Is there a reason why this should be treated any differently from non-const variable templates and their explicit specializations? If I try template<typename T> bool var = true; template<> bool var<int> = false; bool *p = &var<char>; with older clang++, older g++ or older ICC, all those have comdat _Z3varIcE and non-comdat global non-weak _Z3varIiE. So the DR just turns the same for const/constexpr variable templates and their specializations too.
(In reply to Jonathan Wakely from comment #6) > It works if I add 'inline' to the explicit specialization. Or static. inline will only work for C++17, while variable templates are in C++14 already. And the DR applies to all.
(In reply to Jakub Jelinek from comment #8) > So the DR just turns the same for const/constexpr variable templates and > their specializations too. Yeah, I guess it's consistent.
And template <int N> int foo (void) { return N; } template <> int foo <42> (void) { return -42; } int a = foo<15> (); int b = foo<42> (); works the same, _Z3fooILi15EEiv is comdat exported weak, _Z3fooILi42EEiv is non-weak global non-comdat.
Yes but for the function template case if I want to use it in constexpr I add 'constexpr' and it's implicitly inline. For the variable template specialisation it's already constexpr, and I can't define it non-inline in another TU because it needs to be in a header to use in other constexpr functions. So it has to be inline (or static, which can cause odr violations in headers). But this seems like a language problem not a gcc one.