Компиляторы (clang-5.0.0
, GCC-7.3
, ICC-18
и MSVC-19
) расходятся по доступности членов A
ниже.
class A {
template <class> static constexpr int f() { return 0; }
template <int> struct B {};
template <class T> using C = B<f<T>()>;
};
Действительно, рассмотрим следующие способы использования:
template <class T> using D = A::C<T>;
int main() {
// | clang | gcc | icc | msvc
(void) A::f<int>(); // 1: | f | f | f | f, (C)
(void) A::B<0>{}; // 2: | B | | B | B, (C)
(void) A::C<int>{}; // 3: | C, f | | C | C
(void) D<int>{}; // 4: | f | | C | C
}
В таблице справа показано, какие члены должны быть опубликованы каждым компилятором для принятия кода (при компиляции для С++ 14).
ИМХО, ICC и MSVC (игнорируя (C)
записи) выглядят корректно. За исключением первой строки, GCC, похоже, полностью игнорирует доступность.
Я не согласен с clang, когда требуется, чтобы f
был общедоступным для создания экземпляров A::C<int>
и D<int>
. Как и ICC и MSVC, я думаю, что C
и только C
должны быть публичными. Это правда, что C
использует f
но разве это не деталь реализации? Обратите внимание, что C
также использует B
Если clang были верны, то почему он не требует, чтобы B
был публичным?
Наконец, давайте рассмотрим записи (C)
. MSVC требует, чтобы C
был общедоступным, когда он впервые встречает определение D
, то есть MSVC жалуется на то, что C
является частным.
Мои вопросы:
- Прав ли я (и ICC) в моем анализе? Иначе какой другой компилятор верен и почему?
- Является ли проблема MSVC еще одним воплощением ошибки двухфазной реализации в msvc?
Обновление: Что касается GCC, похоже, это ошибка, о которой сообщалось в комментарии 8, здесь.