Quantcast
Viewing all articles
Browse latest Browse all 22037

Why do the usual access control checking applies to names used to specify explicit instantiation when accessed through template parameters?

The C++11/14 standards state the following in note 14.7.2/12 [temp.explicit]:

The usual access checking rules do not apply to names used to specify explicit instantiations. [ 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 which would normally not be accessible and the template may be a member template or member function which would not normally be accessible. — end note ]

I would expect to be allowed to use a template if I can instantiate it.

I tried with gcc-4.8.2 and I get the expected behaviour when I access private members of explicitly named classes. However, the access checking rules do apply when I access private members through template parameters. Is this a bug in gcc, or am I missing something?

In the code below, the only difference between 'succeeds' and 'fails' is that the former accesses the private member directly via 'A', while the latter accesses it via the template parameter 'T'. The compiler complains that privateFoobar is private in that context.

#include <iostream>
#include <string>

struct A
{
private:
    std::string privateFoobar() {return "private foobar!";}
};

typedef std::string (A::*Foobar)();

template <class Type, Type value>
struct Access
{
    static Type getValue() {return value;}
};

template <class T>
struct IndirectAccess
{
    static Foobar succeeds() {return Access<Foobar, &A::privateFoobar>::getValue();}
    static Foobar fails() {return Access<Foobar, &T::privateFoobar>::getValue();}
};

template class Access<Foobar, &A::privateFoobar>;

int main() {
    std::cout << (A().*Access<Foobar,&A::privateFoobar>::getValue())() << std::endl;
    std::cout << (A().*IndirectAccess<A>::succeeds())() << std::endl;
    std::cout << (A().*IndirectAccess<A>::fails())() << std::endl;
}

In case you are wondering what is the use case for such a sackable offence: creating a framework that would automate the configuration of an application based on implementation choices for the selected components.


Viewing all articles
Browse latest Browse all 22037

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>