9
struct X{
    template<class T>
    X(){}
};

Is it possible to instantate such a type?

Xeo
  • 129,499
  • 52
  • 291
  • 397
  • Are you missing something. You can't return from a constructor? – Lee Louviere Jun 03 '11 at 17:21
  • possible duplicate of [Can the template parameters of a constructor be explicitly specified?](http://stackoverflow.com/questions/2861839/can-the-template-parameters-of-a-constructor-be-explicitly-specified) – sth Oct 23 '11 at 18:53

1 Answers1

12

Yes, it is possible to have such a constructor, but it's impossible to call it. All the template parameters of a templated constructor must be deduced from the parameter list or have a default value. In Your example you can't instantiate the class.

[temp.mem]

[ Note: Because the explicit template argument list follows the function template name, and because conversion member function templates and constructor member function templates are called without using a function name, there is no way to provide an explicit template argument list for these function templates. —end note ]

Yakov Galka
  • 70,775
  • 16
  • 139
  • 220
  • The note is not entirely correct. While it is correct that you cannot call the constructor, it is incorrect that you cannot provide explicit template arguments. The following is entirely fine: `template X::X();`. As is `template<> X::X() { }`. Just for the sake of pedantry. :) – Johannes Schaub - litb Jun 03 '11 at 17:35
  • @Johannes: [I doubt that](http://ideone.com/oPHau). The `` there refers to X which is not a template, so your code is invalid. – Yakov Galka Jun 03 '11 at 17:38
  • 1
    @ybugalobill GCC4.3 is not correct to reject it. `X::X` refers to the constructor(s) of `X`, and `` will pass a template argument list to them, filtering out the constructor template. It may be that this was a late addition and didn't make it into C++03 though. No, that made it into C++03. – Johannes Schaub - litb Jun 03 '11 at 17:39
  • @Johannes: I think you're wrong here. If `X` is a template itself, e.g. `vector`, then `vector::vector` is the non-templated default constructor of `vector`. On the other hand you cannot call the templated constructor of `vector::vector`??? – Yakov Galka Jun 03 '11 at 17:42
  • You may also be interested in http://llvm.org/bugs/show_bug.cgi?id=8236 . `vector::vector` means that you pass a template argument `int` to a constructor template. `class vector::vector` would mean to name the type `vector` (this is the c++0x fix/addition). Note that in this case, the injected class name is not equivalent to the injected class name followed by template arguments, because in this case the *injected class name* actually is not followed by template arguments. The name is *translated* to denote the constructor, instead of the injected class name. – Johannes Schaub - litb Jun 03 '11 at 17:46
  • 1
    @ybungalobill If you feel the need to argue with J S - litb. Please bring your biggest guns. (No penguins were harmed during the writing of this silly comment) – Captain Giraffe Jun 03 '11 at 17:50
  • @Johannes: can you please quote the standard? Because I cannot even derive it through the grammar. – Yakov Galka Jun 03 '11 at 17:51
  • @ybungalobill please tell me what I shall quote and I will do my best to serve you. – Johannes Schaub - litb Jun 03 '11 at 17:56
  • @Johannes: why for a templated X, the second `` in `X::X()` binds to the whole declaration rather than to the second `X`? – Yakov Galka Jun 03 '11 at 18:00
  • @ybugalobill I don't understand what you mean by "to the whole declaration." `X::X` refers to the constructor(s). E.g you can say `tempate<> X::X() { }` to specialize a non-templated constructor. In the `X::X` case, you just pass template arguments to the constructor. See 3.4.3.1p2 in the FDIS. GCC4.5 has an [excellent diagnostic](http://ideone.com/tg0kq). – Johannes Schaub - litb Jun 03 '11 at 18:03
  • @Johannes: I mean why is it parsed as `( X::X ) ` and not `X:: ( X )` (parentheses added for clarity)? OK, nevermind. Thank you anyway. – Yakov Galka Jun 03 '11 at 18:08
  • 1
    @Johannes For starters, you might quote something which shows that the second `X` in `X::X` is the name of a constructor. All I find (off hand) is §12.1/1, which says "Constructors do not have names." And I'd be interested in knowning which construction in §5 is involved; the only one I find is §5.2.3, which treats the element to the left of the `(` as a "simple-type-specifier", not the name of a function (or constructor). – James Kanze Jun 03 '11 at 18:12
  • @James "Constructors do not have names" just means that they don't add member names to their class. That's because name lookup finds them by special tweaks. That is, you name the class type by its injected class name qualified by the same class' name, and it comes up with a reference to the constructor, as the result of name lookup. The construction in 3.4.3.1p2 is involved here (3.4.3.1p1a in c++03). Syntactically, a `X::X` of my very first comment is a declarator-id, having a template-id as the very last component of its qualified-id. – Johannes Schaub - litb Jun 03 '11 at 18:28
  • 1
    @Johannes So you're saying that "Constructors do not have names" doesn't mean what it says? How do we know that? Are there any other statements in the standard that don't mean what they say? And if constructors don't have names, why don't their names conflict with the injected class name? – James Kanze Jun 03 '11 at 18:42
  • 1
    @Johannes As for §3.4.3, I don't think that there's any doubt that given `X::X`, the second `X` will be looked up in the scope of the class `X`. Where class name injection will cause it to find the name of the class. Which means that we're back where we started from. And `X::X` is illegal, because the class `X` isn't a template. – James Kanze Jun 03 '11 at 18:42
  • @James yes, as I think you know pretty well, there are a lot of confusing statements in the Standard. It depends on interpretation, and "Foo do not have names" can pretty well be interpreted as "Foo do not add names anywhere", I believe. Of course that contradicts "... each such member-declaration shall declare at least one member name of the class." (9.2p1). But as I'm sure you know pretty well, there are quite a few contradictions in the spec. – Johannes Schaub - litb Jun 03 '11 at 18:48
  • @James I do not understand your question "... why don't their names conflict with the injected class name?". All I can answer is: *because* they do not have names. See the note at 9.2p13. – Johannes Schaub - litb Jun 03 '11 at 18:53
  • Similar to http://stackoverflow.com/questions/4420828/another-bug-in-g-clang-c-templates-are-fun – Johannes Schaub - litb Jun 03 '11 at 19:23
  • @Johannes Yes. §9.2/1 was the sort of thing I was looking for; something that would contradict with "Constructors do not have names", or at least make it unreasonable. I think a DR is in order, since there is a direct contradiction. With regards to the question here: given `X::X`, is the second `X` the injected name of the class, or the name of the constructor. In the first case, `X::X` is illegal, in the second no. I've always believed the first to be true (and that things like `X::X::X`, `X::X::X::X`, etc. are legal, because we always find the injected name of the class). – James Kanze Jun 06 '11 at 08:26
  • @James `X::X::X` and `X::X::X::X` etc is legal, because the lookup for a name directly preceeding a `::` doesn't consider function names. So a constructor is not an "acceptable lookup result" (direct quote) in a `name::`lookup, and hence the translation of the injected class name to the constructor(s) name is not done when followed by a `::`. *However*, `X::X::X` names the constructor(s) - the last `X` will be translated. That means, you can say `struct X { X(); }; X::X::X() { }`. But you cannot say `X::X::X x;`, (`X::X::X` is not a type). – Johannes Schaub - litb Jun 06 '11 at 10:58
  • @Johannes OK. I understand your point. I'm not totally convinced (what about a member `X::X* pChild`?), but I am convinced that the standard is so ambiguous about this that both readings make perfect sense, even if they're contradictory. I'll submit a DR, and we'll see what the committee says. – James Kanze Jun 06 '11 at 11:07
  • @James I agree that there can be different readings on what "acceptable lookup result" means. There recently was a question about that on the reflector (because GCC interprets it like "in a lookup where function names are considered", but clang doesn't. Clang interprets it somewhat like "in situations where constructors may be declared"). The guy that worded this in the spec said that his intent was GCC's behavior. – Johannes Schaub - litb Jun 06 '11 at 15:42
  • @Johannes That's curious. The wording in §12.1/1 ("A special declarator syntax...") strongly suggests that the constructor name is never found (since there isn't one), and that when the class name appears "followed by a a parameter list, it is used to declare or define the constructor. Which sounds like this special rule only applies to declarations or definitions. Not to mention the problem of what section in §5 applies in an expression like `X::X()` if the second `X` refers to the constructor: §5.2.2, probably, but the semantics don't seem correct. – James Kanze Jun 06 '11 at 16:05
  • @James I agree. I think that 12.1p1 is confusing, because it suggests and says that in the definition of a constructor, the name would refer to the class. Same for p2 which claims ".. they are never found during name-lookup". The special handling of 12.1p1 is really needed for in-class constructor declarations. Now I've never implemented this, but from what I can see, there isn't any special rule needed for out-of-class constructor declarations, despite of what those paragraphs say. – Johannes Schaub - litb Jun 06 '11 at 16:35
  • @James I think that 5.2.2 would apply, but 3.4.3.1p2 restricts the use of a constructor name as follows. "Such a constructor name shall be used only in the declarator-id of a declaration that names a constructor or in a using-declaration" – Johannes Schaub - litb Jun 06 '11 at 16:42
  • @Johannes The problem is also that §5.2.2 doesn't have the correct semantics. It doesn't provide for everything necessary to create a new variable (allocating memory, etc.). §5.2.3 has the semantics we want. – James Kanze Jun 06 '11 at 18:31