c++ - 放弃 C++20 中显式函数模板特化的访问检查规则

标签 c++ gcc clang c++20 compiler-bug

[temp.spec]/6通过 P0692R1 的实现添加到 C++20 (特化访问检查)[ 重点 矿]:

[temp.spec]/6 The usual access checking rules do not apply to names in a declaration of an explicit instantiation or explicit specialization, with the exception of names appearing in a function body, default argument, base-clause, member-specification, enumerator-list, or static data member or variable template initializer. [ Note: In particular, the template arguments and names used in the function declarator (including parameter types, return types and exception specifications) may be private types or objects that would normally not be accessible. — end note ]


事实上,这将使以下程序在 C++20 中形成良好的格式:
class A { class B {}; };

template<typename T> void foo() {};
template<> void foo<A::B>() {}

int main() {}
然而,GCC (HEAD 11.0.0 20201121; DEMO ) 和 Clang (HEAD 12.0.0; DEMO ) 都拒绝上述程序(因为 -std=c++20/-std=c++2a 引用私有(private)访问)

GCC:

'class A::B' is private within this context

Clang:

error: 'B' is a private member of 'A'

GCC 将 P0692R1 列为已实现:
  • GCC: C++ Standards Support in GCC

  • 而 Clang 将其 P0692R1 的实现列为部分:
  • C++ Support in Clang: C++20 implementation status


  • 这里 C++20 中的正确行为是什么,上面的程序是格式正确的(GCC 错误/Clang 没有完全实现)还是 GCC 和 Clang 拒绝它是正确的?
  • 最佳答案

    What is the correct behaviour in C++20 here, is the program above well-formed (GCC bug / Clang not fully implemented) or are GCC and Clang correct to reject it?


    正如 OP 中已经引用的那样,[temp.spec]/6 支持此功能,并且程序格式良好。特别是,下面的所有片段 (A) 到 (D) 都是格式良好的:
    // (A)
    class A { class B {}; };
     
    template<typename T> struct S {};
    template<> struct S<A::B> {};
    
    // (B)
    class A { class B {}; };
     
    template<typename T> void foo() {};
    template<> void foo<A::B>() {}
     
    // (C)
    class A { class B {}; };
     
    template<typename T>
    constexpr bool v = false;
    
    template<>
    constexpr bool v<A::B> = true;
    
    // (D)
    class A { class B {}; };
    
    template<typename T, typename U> struct S {};
    template<typename U> struct S<A::B, U> {};
    template<typename T> struct S<T, A::B> {};
    
    GCC 错误地拒绝(B)和(C)(正确接受(A)和(D)),而 Clang 错误(1)拒绝(B)到(D)(正确接受(A))。
    错误报告:
  • GCC(已确认):[C++20][P0692R1] Access checking not waived for declarations of explicit specializations of function and variable templates
  • clang :[P0692R1] Access checking not waived for declarations of explicit specializations of function and variable templates

  • (1) 请注意,Clang(在 OP 中突出显示)已将 P0692R1 的实现状态标记为“部分”,因此这可能不是 Clang 错误,而是尚未实现的功能 C++2a/C++20 .

    关于c++ - 放弃 C++20 中显式函数模板特化的访问检查规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64960135/

    相关文章:

    c - -lcs50 命令行参数在 clang 中有什么作用?

    c++ - 二维数组的行为

    c++ - gcc -I 和 -L 选项似乎不起作用

    c++ - 从 C++ 代码中剥离注释,同时保留行号

    c++ - LLVM 最大的好处是什么?

    c - Makefile,clang OK,gcc错误

    c++ - 为什么 'int'只用作int,为什么不用作C++中的std::int?

    c++ - 注册表模式中的段错误 11

    c++ - 除了最右边数字为 "6"的任何整数输入都有效,但任何数字如 ...6 都会导致段错误,为什么?

    gcc - 为什么这个SSE2程序(整数)生成movaps(浮点)?