Подтвердить что ты не робот

Могут ли имена typedef использоваться для объявления или определения конструкторов?

Standardese:

[class.ctor] 12.1/1 говорит

Для объявления или определения конструктора используется специальный синтаксис декларатора. Синтаксис использует:

    - необязательный spec-specifier-seq, в котором каждый спецификатор-спецификатор является либо спецификатором функции, либо constexpr,

    - имя класса конструкторов и

    - список параметров

в этом порядке.

[class.name] 9.1/4 говорит

Имя typedef-name (7.1.3), которое называет тип класса или cv-квалификацию его версия также является именем класса. Если имя typedef, которое Тип класса cv-qual используется, когда требуется имя класса, cv-квалификаторы игнорируются. Имя typedef не должно использоваться как идентификатор в заголовке класса.

Также [expr.prim.general] 5.1.1/8 говорит

В тех случаях, когда используется имя класса:: class-name, а также имена двух классов к тому же классу, это обозначение называет конструктор (12.1).


Применение:

Мне кажется, что объявление конструктора должно быть разрешено с использованием имен typedef (несмотря на то, что 12.1/1 не использует курсивом имя класса).

Например, данный:

struct Foo;
typedef Foo Bar;

затем

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

или вместо этого

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

затем

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

или

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

или

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

Любое из них должно быть законным. Однако никто, кажется, не принимает определения 2 или 3, MSVC принимает 1, а MSVC, clang и gcc все принимают 4.

Правильно ли мой анализ, и все эти компиляторы ошибочны?

4b9b3361

Ответ 1

§12.1/3 рабочий проект N3337 (февраль 2012 г.) гласит

Имя typedef не должно использоваться как имя класса в объявлении-id для объявления конструктора.

Это исключает (1).

В §12.1/1, по-видимому, используется термин "декларация" для обеих деклараций и определений:

Для объявления или определения конструктора используется специальный синтаксис декларатора. [...] В таком заявлении [...]

(без прямого упоминания "определений" ). Я думаю, что это немного неясно, относится ли это к определениям вне класса или только к встроенным определениям. Если это относится ко всем видам определений, это также исключает (2) и (3). (4) должно быть законным в любом случае.

Ответ 2

К сожалению, это работает в Microsoft C, но не в других компиляторах, которые я использую. Особенно когда желательно в шаблонах. Может быть, я не знаю "совместимого со стандартами способа", но это действительно полезно в шаблонах.

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) { ... }
}.

Может быть, другой вопрос, возможно, это не работает в GCC, Clang и т.д. Есть ли способ сделать это в этих других компиляторах?