模板参数中的访问控制

Pas*_* By 17 c++ language-lawyer

灵感来自这个声称破坏访问控制系统的答案,我编写了以下最小版本的黑客

template<typename T>
inline T memptr{};

template<auto Val>
struct setptr
{
    struct setter { setter() { memptr<decltype(Val)> = Val; } };
    static setter s;
};

template<auto Val>
typename setptr<Val>::setter setptr<Val>::s{};
Run Code Online (Sandbox Code Playgroud)

然后用作

class S
{
    int i;
};

template struct setptr<&S::i>;

auto no_privacy(S& s)
{
    return s.*memptr<int S::*>;
}
Run Code Online (Sandbox Code Playgroud)

为什么不template struct setptr<&S::i>;违反访问控制?

是因为[class.access]

访问控制统一应用于所有名称,无论名称是从声明还是表达式引用.

具体是不包括实例化?在哪种情况下,为什么不包括实例化?

勘误表:显式实例化也被归类为声明.

Gui*_*cot 11

来自[temp.spec]/6(强调我的):

通常的访问检查规则不适用于显式实例化或显式特化的声明中的名称,但出现在函数体,默认参数,base子句,成员规范,枚举器列表或静态数据中的名称除外成员或变量模板初始化程序.[注意:特别是,函数声明符中使用的模板参数和名称(包括参数类型,返回类型和异常规范)可能是通常无法访问的私有类型或对象. - 结束说明]

因此,您看到这种技术滥用此规则,这主要是允许类的实现者使用私有类型或其他私有实体专门化模板(如特征)