Uczynienie parametru szablonu przyjacielem?

Przykład:

template<class T>
class Base {
public:
    Base();
    friend class T;
};
Teraz to nie działa... Jest na to jakiś sposób? [[2]} właśnie staram się zrobić taki sealer klasy ogólnej:
class ClassSealer {
private:
   friend class Sealed;
   ClassSealer() {}
};
class Sealed : private virtual ClassSealer
{ 
   // ...
};
class FailsToDerive : public Sealed
{
   // Cannot be instantiated
};

Znalazłem ten przykład na tej stronie gdzieś, ale nie mogę go znaleźć... ( tutaj )

Wiem, że istnieją inne sposoby na zrobienie tego, ale teraz jestem ciekawa, czy naprawdę możesz zrobić coś takiego.

Author: Community, 2009-03-31

3 answers

Jest to wyraźnie zabronione w standardzie, nawet jeśli niektóre wersje VisualStudio na to zezwalają.

C++ Standard 7.1.5.3, paragraf 2

3.4.4 opisuje przebieg wyszukiwania nazwy dla identyfikatora w opracowano na podstawie materiału źródłowego. Jeśli identifier resolves to a class-name or enum-name, opracowany-Typ-specifier wprowadza to w deklaracji to samo sposób prosty-typ-specifier wprowadza jego nazwa typu. Jeśli identifier resolves do typedef-name Lub a typ szablonu-parametr, opracowano na podstawie materiału źródłowego. źle ukształtowany. [Uwaga: oznacza to, że, w szablonie klasy z typ szablonu-parametr T, declaration friend class T ; is źle ukształtowany. ]

Uznaję powyższy kod jako wzorzec do zapieczętowania (zablokowania rozszerzenia) klasy. Jest jeszcze jedno rozwiązanie, które tak naprawdę nie blokuje rozszerzenia, ale będzie oznaczać nieskomplikowane rozszerzenie z klasy. Jak widać w ADOBE Source Library :

namespace adobe { namespace implementation {
template <class T>
class final
{
protected:
   final() {}
};
}}
#define ADOBE_FINAL( X ) private virtual adobe::implementation::final<T>

Z użyciem:

class Sealed : ADOBE_FINAL( Sealed )
{//...
};

Podczas gdy pozwala na rozszerzenie, jeśli naprawdę go wymusisz:

class SealBreaker : public Sealed, ADOBE_FINAL( Sealed )
{
public:
   SealBreaker() : adobe::implementation::final<Sealed>(), Sealed() {}
};

To ograniczy użytkowników od omyłkowo to zrobić.

EDIT :

Nadchodzący standard C++11 pozwala zaprzyjaźnić się z argumentem typu o nieco innej składni:

template <typename T>
class A {
   // friend class T; // still incorrect: elaborate type specifier
   friend T;          // correct: simple specifier, note lack of "class"
};
 37
Author: David Rodríguez - dribeas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-07 21:52:35

Znalazłem prostą sztuczkę, aby zadeklarować parametry szablonu jako znajomych:

template < typename T>
struct type_wrapper 
{ 
   typedef T type; 
}; 


template < typename T> class foo 
{ 
  friend class type_wrapper < T>::type 
};   // type_wrapper< T>::type == T

Nie wiem jednak, jak mogłoby to pomóc w zdefiniowaniu alternatywnej wersji uszczelniacza klasy.

 19
Author: A Milton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-10 00:36:58

Czy naprawdę musisz to robić? Jeśli chcesz uniemożliwić komuś korzystanie z twojej klasy, po prostu dodaj komentarz i spraw, aby Destruktor nie był wirtualny.

 3
Author: rlbond,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-31 19:30:22