【发布时间】:2018-08-10 18:16:18
【问题描述】:
编译器(clang-5.0.0、GCC-7.3、ICC-18 和 MSVC-19)与 w.r.t 不同。以下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
}
右侧的表格显示了每个编译器需要公开哪些成员才能接受代码(针对 C++14 编译时)。
恕我直言,ICC 和 MSVC(忽略 (C) 条目)看起来是正确的。除了第一行,GCC 似乎完全忽略了可访问性。
当需要 f 公开以实例化 A::C<int> 和 D<int> 时,我不同意 clang。像 ICC 和 MSVC 一样,我认为 C 并且只有 C 需要公开。 C 确实使用了f,但这不是实现细节吗?注意C 也使用B。如果 clang 是正确的,那为什么它不需要 B 也是公开的呢?
最后,让我们考虑(C) 条目。 MSVC在第一次遇到D的定义时要求C是public的,即MSVC抱怨C是private的。
我的问题是:
- 我的分析是否正确(ICC 也是如此)?否则哪个其他编译器是正确的,为什么?
- 是 MSVC 问题的另一个体现 two-phase instantiation bug in msvc?
更新:关于 GCC,这似乎是评论 8 here 中报告的错误。
【问题讨论】:
-
clang 或 icc 和 msvc 在第 3 行是否正确的问题很有趣。此外,很高兴知道 gcc 的怪异之处。您是否在这里提交了有关 gcc 行为的错误报告?
-
@einpoklum 我还没有填写错误报告。在更多的人确认我的期望后,我会这样做。如果事实证明 clang 也是错误的,那么我也会在那里填写错误报告。我不会为 msvc 做,因为(如果我的分析是正确的)他们已经知道了。
-
您是否在
/permissive-模式下使用MSVC 进行编译?如果没有那个标志,它可能会表现得很奇怪 -
D格式不正确,因为无法进行有效的特化(但只有在未实例化时才为 NDR)。 -
CWG1554 似乎相关。
标签: c++ gcc clang private encapsulation