Can typedef names be used to declare or define constructors?

Viewed 4138

Standardese:

[class.ctor] 12.1/1 says

A special declarator syntax is used to declare or define the constructor. The syntax uses:

    — an optional decl-specifier-seq in which each decl-specifier is either a function-specifier or constexpr,

    — the constructor’s class name, and

    — a parameter list

in that order.

[class.name] 9.1/4 says

A typedef-name (7.1.3) that names a class type, or a cv-qualified version thereof, is also a class-name. If a typedef-name that names a cv-qualified class type is used where a class-name is required, the cv-qualifiers are ignored. A typedef-name shall not be used as the identifier in a class-head.

Also [expr.prim.general] 5.1.1/8 says

Where class-name :: class-name is used, and the two class-names refer to the same class, this notation names the constructor (12.1).


Application:

This seems to me to say that declaring a constructor should be allowed using typedef names (despite the fact that 12.1/1 doesn't use an italicized class-name).

For example, given:

struct Foo;
typedef Foo Bar;

then

struct Foo { Bar() {} }; // defines Foo's constructor. - 1

or instead given

struct Foo;
struct Foo { Foo() };
typedef Foo Bar;

then

Foo::Bar() {}; // defines Foo's constructor - 2

or

Bar::Bar() {}; // defines Foo's constructor - 3

or

Bar::Foo() {}; // defines Foo's constructor - 4

Any of these should be legal. However nobody seems to accept definitions 2 or 3, MSVC accepts 1, and MSVC, clang, and gcc all accept 4.

Is my analysis correct, and are all these compilers wrong?

2 Answers

Well annoyingly it seems to work in Microsoft C but not other compilers I use. Especially when desirable in templates. Maybe I don't know the "standards compliant way" to do this, but It is really useful in templates.

template<class T, class T1, ... /* messy, verbose */ >
class MyTemplate {
protected:
    typedef MyTemplate<T,T1, ... /* messy, verbose */ > SimplerName;

    // declare a constructor
    SimplerName(int arg) { ... }
};
class SubClass
    : public MyTemplate<x,y....>
{
public:
    SubClass(int arg) : SimplerName(arg) { ... }
}.

Maybe another question perhaps This does not work in GCC, Clang etc, Is there a way to do this in those other compilers ?

Related