Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template instantiation of templated class constructor

This fails to compile with clang++, can anybody explain why ? (this compiles fine with g++)

struct X
{
  template <typename T> X() {}
};

template X::X<int>();

int main() { return 1; }



instantiate.cc:7:13: error: qualified reference to 'X' is a constructor name rather than a type in this context
template X::X<int>();
            ^
instantiate.cc:7:14: error: expected unqualified-id
template X::X<int>();
             ^
2 errors generated.
like image 869
Matthieu G Avatar asked Jan 24 '23 22:01

Matthieu G


2 Answers

Constructors don't have names. As much is said in [class.ctor]/1. They are special members that get defined by using the name of the class. But they themselves are nameless. While C++ allows us to reference c'tors in certain contexts by using the class name, those are limited. In general, we cannot name a c'tor.

And that is where the issue lies. To explicitly specify template arguments we must use the name of the templated entity. Constructors don't have names, and so we cannot specify their arguments explicitly.

This is the subject of a note in [temp.arg.explicit] that summarizes the intent of the normative text.

7 [ 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 ]

We can still instantiate or specialize constructors, but only if the template arguments don't have to be explicitly specified (if they are deducible, or come from a default template argument). E.g

struct X
{
  template <typename T> X(T) {}
};

template X::X(int); // This will work

So Clang is not wrong to reject your code. And it's possible GCC is offering an extension. But ultimately, the standard doesn't offer a way to provide template arguments explicitly to constructor templates.


And upon further digging, there's CWG581, further confirming Clang's behavior is the intended one. It also seems to have made its way into the latest standard revision with some changes to the normative text.

like image 56
StoryTeller - Unslander Monica Avatar answered Feb 03 '23 18:02

StoryTeller - Unslander Monica


I think Clang is correct. Even Gcc allows it, the templated constructor can't be used at all. The template parameter can't be deduced and we can't specify template argument explicitly for constructor template.

[temp.arg.explicit]/2

Template arguments shall not be specified when referring to a specialization of a constructor template ([class.ctor], [class.qual]).

[temp.arg.explicit]/8

[ Note: Because the explicit template argument list follows the function template name, and because constructor templates ([class.ctor]) are named without using a function name ([class.qual]), there is no way to provide an explicit template argument list for these function templates. — end note ]

like image 31
songyuanyao Avatar answered Feb 03 '23 17:02

songyuanyao