4
struct B
{
    int a;
    void foo() {a = 5;}
};

template <typename T>
struct A
{
    A(int i) { B::foo(); }
    A(double d) {}
};

int main()
{
    A<int> a(5.0);
}

gcc 4.7.2 compiles it without errors. clang 3.4svn complains:

$ clang -Wall -Wextra test.cpp 
test.cpp:10:16: error: call to non-static member function without an object argument
        A(int i) { B::foo(); }
                   ~~~^~~

Of course the code is wrong, but which compiler is conformant with the standard?

It's also strange that clang doesn't print any 'in instantiation' note like gcc does if you use 5 instead of 5.0:

$ gcc test.cpp 
test.cpp: In instantiation of ‘A<T>::A(int) [with T = int]’:
test.cpp:15:12:   required from here
test.cpp:9:13: error: cannot call member function ‘void B::foo()’ without object
Trass3r
  • 5,858
  • 2
  • 30
  • 45
  • 1
    You need an object to call `foo` with. That's a given. – chris Jul 11 '13 at 16:33
  • 2
    Trying to locate the exact quote, but both compilers are right and your code is wrong. A template for which there is no valid instantiation is incorrect even if it is never instantiated. This applies to the `A(int)` constructor, there is no type for which that constructor is valid. The standard does not require diagnosing this problem, so gcc is still compliant. – David Rodríguez - dribeas Jul 11 '13 at 16:35
  • 1
    @DavidRodríguez-dribeas: I think you're looking for 14.6/8, but does that apply to non-template member functions of a class template? I don't think so – Andy Prowl Jul 11 '13 at 16:41
  • @AndyProwl: The example given in 14.6/8 uses a non-template member function of a class template, so it does apply. – interjay Jul 11 '13 at 16:49
  • @AndyProwl: Yes, that is the relevant quote and I believe it applies. The rationale: the quote refers to first-phase lookup which is done independent of whether the template is instantiated at all, and the quote explicitly states it: *even if it is not instantiated, it is still ill-formed* – David Rodríguez - dribeas Jul 11 '13 at 16:50
  • @DavidRodríguez-dribeas: I do understand the rationale and I find what you say reasonable, but I still don't understand how 14.6/8 implies it: it explicitly says "*for a template*", not "*for the a member function of a template*". I think the two are different things – Andy Prowl Jul 11 '13 at 16:54

1 Answers1

5

Your program is incorrect, and both compilers are right as the standard does not require a diagnostic from a conforming compiler (letting gcc ignore it). A template for which there can be no valid instantiation (specialization in standard jargon) is incorrect even if that template is never instantiated.

In your case, the name B::foo() inside A<T>::A(int) is a non-dependent name, so it needs to be resolved during the first phase lookup, and it can only refer to the B class defined above. Because it is not a static member function, but a non-static one, the code is incorrect, regardless of the type T used to instantiate the A<T> template and the program is ill-formed.

The relevant quote is from 14.6 [temp.res]/8:

Knowing which names are type names allows the syntax of every template definition to be checked. No diagnostic shall be issued for a template definition for which a valid specialization can be generated. If no valid specialization can be generated for a template definition, and that template is not instantiated, the template definition is ill-formed, no diagnostic required.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • I don't understand why 14.6/8 applies here: the constructor is not a template, and 14.6/8 applies to templates for which no valid specialization exists (as far as I can understand it). A valid specialization of `A` exists here – Andy Prowl Jul 11 '13 at 16:48
  • 2
    A member function of a class template is a template itself, as it requires instantiation. – James Kanze Jul 11 '13 at 16:50
  • @AndyProwl: On top of James's argument (which I believe correct), the fact that the example in that same paragraph includes code similar to the one in the question (`p = j;` where neither `p` nor `j` are dependent names) seems to indicate that when the rule was written with precisely this intent. – David Rodríguez - dribeas Jul 11 '13 at 16:52
  • @DavidRodríguez-dribeas: Yes, interjay pointed that out (I overlooked the example). So obviously your answer is correct and this is the intended meaning of the wording of 14.6/8. But I do not agree with Jame's statement that "a member function of a template is a template" - I amy be wrong, but I would need to get some explanation. I am used to see the Standard distinguish between "member templates" and "non-template members" of a class template. – Andy Prowl Jul 11 '13 at 16:57
  • @JamesKanze: "*It requires instantiation*" -> I agree. "*Is a template itself*" -> I disagree. Can you provide evidence of the term "template" including member functions of a class template? – Andy Prowl Jul 11 '13 at 16:59
  • 1
    @AndyProwl You're right that the standard _usually_ refers to them as "members of a class template", but §14.5.1/3 says "[...]the member definition is defined as a template definition[...]" (and I can't imagine different rules applying for functions defined within the class). And there is a definite intent to allow as much checking as is possible where the template was defined; otherwise, there's no need for `typename`. – James Kanze Jul 11 '13 at 17:24
  • @JamesKanze: I do agree that the rule make sense, I just have troubles understanding how it is implied by the current wording. As for the paragraph you quoted, I always took it as a way of specifying how the member functions should be defined outside of a class - not as a way of specifying that "*members of a class template are essentially templates*". I might be wrong, but if that is the intended meaning (and it really seems it is), then I find the current wording very misleading. – Andy Prowl Jul 11 '13 at 18:36
  • @AndyProwl It could certainly be improved. But then, there are a lot of places where one could say that. – James Kanze Jul 12 '13 at 07:46
  • Does anyone know the rationale for not requiring a diagnostic? – Trass3r Jul 12 '13 at 13:10
  • 1
    @Trass3r: template processing, and in particular the first phase in two-phase lookup, are done (or not) in different ways by different compilers. While you might wish to be able to detect issues early (first phase) in general, there are compilers that don't perform the first phase at all, and the complexity of checks in those that do have two phases differ. Note that this could be potentially expensive, in that if this was mandatory, the checks would have to be performed for all templates in all translation units in which they are defined, regardless of whether the template is used. – David Rodríguez - dribeas Jul 12 '13 at 13:39
  • 1
    [...] any extra work added here would impact basically *all* translation units (assuming standard headers are usually included). While today processors are quite fast, this has not always been the same, and templates are slow to compile already. At any rate, these are *my* opinions, which are not backed up by anything at all :) – David Rodríguez - dribeas Jul 12 '13 at 13:40
  • Ah makes sense, I think you should update your answer nevertheless. – Trass3r Jul 15 '13 at 08:08