Bug 56480 - Explicit specialization in a namespace enclosing the specialized template
Summary: Explicit specialization in a namespace enclosing the specialized template
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.8.0
: P3 normal
Target Milestone: 7.0
Assignee: Jason Merrill
URL:
Keywords: rejects-valid
: 63705 78274 (view as bug list)
Depends on:
Blocks:
 
Reported: 2013-02-28 08:17 UTC by Nathan Ridge
Modified: 2017-01-10 22:11 UTC (History)
7 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2013-03-05 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Nathan Ridge 2013-02-28 08:17:48 UTC
The following code:


namespace Foo 
{
    template <typename T>
    struct Meow
    {
    };
}

template <>
struct Foo::Meow<int>
{
};


fails to compile with gcc 4.8 (tested with 20130224 snapshot). 

I believe this code should be accepted in C++11 mode as per [temp.expl.spec] p2: "An explicit specialization shall be declared in a namespace enclosing the specialized template." This is a relaxation of the C++03 wording: "An explicit specialization shall be declared in the namespace of which the template is a member".

Recent versions of clang and MSVC compile the above code in C++11 mode.
Comment 1 Jonathan Wakely 2013-03-05 01:29:27 UTC
I think this is http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#374
Comment 2 Nathan Ridge 2013-03-05 04:30:26 UTC
(In reply to comment #1)
> I think this is
> http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#374

Ah, I see. The code is accepted if a declaration (without definition) of the specialization is placed in the namespace. Didn't realize that.
Comment 3 Zhihao Yuan 2013-11-29 23:49:44 UTC
(In reply to Nathan Ridge from comment #2)
> (In reply to comment #1)
> > I think this is
> > http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#374
> 
> Ah, I see. The code is accepted if a declaration (without definition) of the
> specialization is placed in the namespace. Didn't realize that.

?? That was the c++03 status, and the new wording ("or to a specialization
thereof") relaxed this requirement.

Has this been implemented?
Comment 4 Markus Trippelsdorf 2014-11-01 15:51:27 UTC
*** Bug 63705 has been marked as a duplicate of this bug. ***
Comment 5 Markus Trippelsdorf 2014-11-01 18:05:40 UTC
Two possible fixes: 

1)
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 2cf10f442f68..09a545496fa8 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -785,8 +785,12 @@ check_specialization_namespace (tree tmpl)
     return true;
   else
     {
-      permerror (input_location, "specialization of %qD in different namespace", tmpl);
-      permerror (input_location, "  from definition of %q+#D", tmpl);
+      if (cxx_dialect < cxx11)
+       {
+         permerror (input_location, "specialization of %qD in different "
+                    "namespace", tmpl);
+         permerror (input_location, "  from definition of %q+#D", tmpl);
+       }
       return false;
     }
 }

2)
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 2cf10f442f68..1171b5d736d5 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -780,15 +780,15 @@ check_specialization_namespace (tree tmpl)
       error ("specialization of %qD must appear at namespace scope", tmpl);
       return false;
     }
-  if (is_associated_namespace (current_namespace, tpl_ns))
-    /* Same or super-using namespace.  */
-    return true;
-  else
+  if (!is_associated_namespace (current_namespace, tpl_ns) &&
+      (cxx_dialect < cxx11))
     {
       permerror (input_location, "specialization of %qD in different namespace", tmpl);
       permerror (input_location, "  from definition of %q+#D", tmpl);
       return false;
     }
+
+  return true;
 }
 
 /* SPEC is an explicit instantiation.  Check that it is valid to


The following testcases:

g++.dg/template/spec17.C
g++.dg/template/spec25.C
g++.dg/template/spec36.C
g++.old-deja/g++.ns/template13.C
g++.old-deja/g++.pt/explicit73.C 
g++.old-deja/g++.pt/lookup10.C

would have to be updated.
Comment 6 Jakub Jelinek 2015-04-22 11:59:32 UTC
GCC 5.1 has been released.
Comment 7 Richard Biener 2015-07-16 09:11:56 UTC
GCC 5.2 is being released, adjusting target milestone to 5.3.
Comment 8 Richard Biener 2015-12-04 10:44:26 UTC
GCC 5.3 is being released, adjusting target milestone.
Comment 9 Richard Biener 2016-06-03 10:04:48 UTC
GCC 5.4 is being released, adjusting target milestone.
Comment 10 Pedro80 2016-10-30 18:44:44 UTC
What an annoying bug, can this finally be fixed?!
Our code base heavily relies on this feature alone as it's used in reflection code to specialize templates for certain types and it's done by expansion of preprocessor macro.
This bug alone prevents us from using gcc as we heavily use this perfectly normal code:

namespace NS1 {
  namespace NS2 {
    template<class T> int someFunction();
  }
}

#define REGISTER(type) template<>NS1::NS2::someFunction<type>() { return something; }

and then that REGISTER macro can be used in global namespace or inside NS1 or NS2.
Comment 11 Jason Merrill 2016-12-01 19:54:22 UTC
Author: jason
Date: Sun Nov 13 06:51:23 2016
New Revision: 242348

URL: https://gcc.gnu.org/viewcvs?rev=242348&root=gcc&view=rev
Log:
	DR 374 - specialization in outer namespace

	PR c++/56840
	* pt.c (check_specialization_namespace): Allow any enclosing
	namespace.
	(check_unqualified_spec_or_inst): New.
	(check_explicit_specialization): Call it.
	* parser.c (cp_parser_elaborated_type_specifier)
	(cp_parser_class_head): Call it.

Added:
    trunk/gcc/testsuite/g++.dg/cpp0x/explicit-inst1.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/cp-tree.h
    trunk/gcc/cp/decl.c
    trunk/gcc/cp/name-lookup.c
    trunk/gcc/cp/parser.c
    trunk/gcc/cp/pt.c
Comment 12 Jason Merrill 2017-01-10 22:11:44 UTC
*** Bug 78274 has been marked as a duplicate of this bug. ***