Ответ не ясен С++

Вот тестовый вопрос:

Рассмотрим следующий код:

class A {
    typedef int I; // private member
    I f();
    friend I g(I);
    static I x;
};

Какое из следующего допустимо:

a. A::I A::f() { return 0; }
b. A::I g(A::I p = A::x);
c. A::I g(A::I p) { return 0; }
d. A::I A::x = 0;

Ответ на этот вопрос считается правильным только для первой версии (а.), но почему? Все они действительны, на мой взгляд. Даже проверены все они компилируются успешно. Почему правильный ответ правильный?

Ответ 1

Тот, кто написал исходный ответ на тест, ошибочен.

  • Этот пример приходит (точно) из самого стандарта С++, раздел § 11/7, [class.access] и был скопирован тем, кто написал "тест"

Пример идет еще дальше в стандарте, с шаблонами (я опускаю их здесь):

      class A {
          typedef int I;      // private member
          I f();
          friend I g(I);
          static I x;
      };

      A::I A::f() { return 0; }
      A::I g(A::I p = A::x);
      A::I g(A::I p) { return 0; }
      A::I A::x = 0;
  • Указание стандарта для объяснения:

Здесь все использование A::I хорошо сформировано, потому что A::f и A::x являются члены класса A и g являются друзьями класса A. Это означает, что для Например, проверка доступа при первом использовании A::I должна быть откладывается до тех пор, пока не будет определено, что это использование A::I является возвратом тип члена класса A.]

Ответ 2

Все они действительны для С++.

Вот точный код, это пример из самого стандарта:

http://www.open-std.org/jtc1/sc22/open/n2356/access.html

Вот как я их разбираю:

a. A::I A::f() { return 0; } // defines A::f() which was previously prototyped

b. A::I g(A::I p = A::x);    // declares prototype g(A::I), but doesn't define it

c. A::I g(A::I p) { return 0; } // defines g(A::I)

d. A::I A::x = 0; // defines static storage for A::x which was previously declared in A

Все они компилируются, как индивидуально, так и коллективно.