Access to the base class of the template before extending the template obtained from

I am trying to publicly infer a class from a template that will force it to inherit from the base class and gain access to protected members. But before the template is expanded, it does not have these rights, so it cannot use the Base element as a template parameter:

using Fun = void (*)(); class Base { protected: // friend class Derived; // ...need this to eliminate complaint static void something(); }; template<Fun F> class Variant : public Base {}; class Derived : public Variant<&Base::something> { // `something()` is protected public: void somethingElse() { something(); // doesn't complain about this `something()` } }; int main() {} 

The strange bit about this for me was that friendship with him generally worked. I wondered if I could "sneak in the door" by putting public virtual inheritance from the database before the option:

 class Derived : public virtual Base, public Variant<&Base::something> 

It did not help.

Question: is there any other trick to avoid explicit mention of all derived classes in the database, but still you have access to the selected protected members from it for template parameters?

(Note. Attempting to do this on an earlier gcc, 4.6.3, it seems that even friendship does not help in this case. Therefore, it seems to be a bit new.)

+5
source share
1 answer

Hold the breaking metaphor. Derive the metaphone class from the database.

 template<typename B> struct something_variant : public B { typedef Variant< & B::something > type; }; class Derived : public something_variant<Base>::type { … 

http://coliru.stacked-crooked.com/a/6bca00455bd3daca

Regarding CWG 372, the critical text in the resolution is this:

[A] Checking the caching of basic qualifiers should be delayed until the entire list of base qualifiers has been scanned.

This has already been adopted in C ++ 11, so it is interesting that your example is rejected. And by plugging the appropriate example code from the C ++ 11 standard into recent Clang and GCC, it demonstrates that they simply did not defer. This is at least a bit unsurprising, since implementation requires some data structure to represent a set of deferred access checks ... a lot of effort for a corner case.

+1
source

Source: https://habr.com/ru/post/1233106/


All Articles