Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 3606594
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 18, 20262026-05-18T21:16:07+00:00 2026-05-18T21:16:07+00:00

Check out the following code (written just for fun) namespace N { template<typename T>

  • 0

Check out the following code (written just for fun)

namespace N
{
   template<typename T>
   struct K
   {

   };
}
template<typename T>
struct X
{
   typename T::template K<T> *p; //should give error 
                                 //N::K<int> has no template member named `K`
};

int main()
{
   X<N::K<int> > l;
}

The code gets compiled on g++(4.5.1) and Clang whereas Comeau and Intel C++ give (similar) errors.

The errors that I get on Comeau are :

"ComeauTest.c", line 13: error: class "N::K<int>" has no member "K"
     typename T::template K<T> *p;
                          ^
          detected during instantiation of class "X<T> [with T=N::K<int>]" at
                    line 18

"ComeauTest.c", line 13: error: expected an identifier
     typename T::template K<T> *p;
                           ^
          detected during instantiation of class "X<T> [with T=N::K<int>]" at
                    line 18

So my question is “Is the code sample ill-formed ?” According to me “Yes”. Does that mean this is yet another bug in g++/Clang?

  • 1 1 Answer
  • 1 View
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-18T21:16:08+00:00Added an answer on May 18, 2026 at 9:16 pm

    Why GCC and Clang think they are right

    K, which is the injected class name, has a dual nature in the scope of K<int>. You can use it without template arguments. Then it refers to K<int> (to its own type).

    It can be followed by a template argument list too. IMO it’s reasonable to say that you need to prefix it with template because of the parser ambiguity with the < that follows. It then refers to the specified type that’s determined by the template arguments.

    So it can be treated as a member template and as a nested type, depending on whether it’s followed by a template argument list. Of course, K is not really a member template. The dual nature of the injected class name seems to me more of a hack anyway, though.

    The Standard has an example that reads like this:

    template <class T> struct Base { };
    template <class T> struct Derived: Base<int>, Base<char> {
       typename Derived::Base b; // error: ambiguous
       typename Derived::Base<double> d; // OK
    };
    

    One might be inclined to conclude from this that the intent is that you could leave off the template. The Standard says

    For a template-name to be explicitly qualified by the template arguments, the name must be known to refer to a template.

    I can’t see how this wouldn’t apply to T::K<T>. If T is a dependent type then you can just lean back because you can’t know what K refers to when parsing it, so to make any sense of the code, you just have to be able to prefix it with template. Notice that n3225 has that example too, but it’s not a defect there: You can officially leave off template if you lookup into the template’s own scope in C++0x (it’s called the “current instantiation”).

    So until now, Clang and GCC are fine.


    Why Comeau is right

    Just to make it even more complicated, we will have to consider the constructors of K<int>. There is a default constructor and a copy constructor implicitly declared. A name K<int>::K will refer to the constructor(s) of K<int> unless the name lookup used will ignore function (constructor) names. Will typename T::K ignore function names? 3.4.4/3 says about elaborated type specifiers, which typename ... is one of:

    If the name is a qualified-id, the name is looked up according its qualifications, as described in 3.4.3, but ignoring any non-type names that have been declared.

    However, a typename ... uses different lookup. 14.6/4 says

    The usual qualified name lookup (3.4.3) is used to find the qualified-id even in the presence of typename.

    The usual qualified lookup of 3.4.3 won’t ignore non-type names, as illustrated by the example attached to 14.6/4. So, we will find the constructor(s) as specified by 3.4.3.1/1a (the additional twist that this only happens when non-types are not ignored was added by a later defect report, which all popular C++03 compilers implement though):

    If the nested-name-specifier nominates a class C, and the name specified after the nested-name-specifier, when looked up in C, is the injected-class-name of C (clause 9), the name is instead considered to name the constructor of class C. Such a constructor name shall be used only in the declarator-id of a constructor definition that appears outside of the class definition.

    So in the end, I think comeau is correct to diagnose this, because you try to put a template argument list onto a non-template and also violate the requirement quoted in the last part (you use the name elsewhere).

    Let’s change it by accessing the injected name by a derived class, so no constructor name translation occurs, and you really access the type so that you really can append the template arguments:

    // just replace struct X with this:
    template<typename T>
    struct X
    {
       struct Derived : T { };
       typename Derived::template K<T> *p;
    };
    

    Everything compiles now with comeau too! Notice I already did problem report to clang about this exact thing. See Incorrect constructor name resolution. BTW, if you declare a default constructor in K, you can see comeau give a better error message if you use T::K<int>

    "ComeauTest.c", line 13: error: overloaded function "N::K<T>::K [with T=int]" is
              not a template
         typename T::template K<T> *p;
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Please check out my following code... public enum LogType { Debug, Info, Warn, Error,
Check out the following snippet of HTML/Javascript code: <html> <head> <script type=text/javascript> var alerts
Please check out my following code String jsonString = writer.toString(); JSONObject jsonObj = new
Check out the following code: private void Foo(object bar) { Type type = bar.GetType();
I have the following code //check out the tags, if it allready exist update
In the following code, I am trying to check if an int (converted to
check out the following test: http://binks.knobbits.org/webgl/texture3.html It's a simple test of cube textures. It
Please check out the following func and its output void main() { Distance d1;
Check out this piece of JavaScript code: (function (w, d) { var loader =
Check out the following screenshot: http://www.jesserosenfield.com/beta/descenders.png My problem is that descending (like the 7

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.