Passer By
Passer By

Reputation: 21160

Access control in template parameters

Inspired from this answer, which claims to subvert the access control system, I wrote the following minimal version of the hack

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{};

which is then used as

class S
{
    int i;
};

template struct setptr<&S::i>;

auto no_privacy(S& s)
{
    return s.*memptr<int S::*>;
}

Why doesn't template struct setptr<&S::i>; violate access control?

Is it because [class.access]

Access control is applied uniformly to all names, whether the names are referred to from declarations or expressions.

specifically doesn't include instantiations? In which case, why doesn't it include instantiations?

Errata: Explicit instantiations are also classified as declarations.

Upvotes: 18

Views: 477

Answers (1)

Guillaume Racicot
Guillaume Racicot

Reputation: 41780

From [temp.spec]/6 (emphasis mine):

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  ]

So this technique you see abuses this rule, which is primarely there to allow implementers of a class specialize templates (such as traits) with private types or other private entities

Upvotes: 11

Related Questions