Making a template parameter a friend?

前端 未结 3 1585
忘掉有多难
忘掉有多难 2020-12-01 04:31

Example:

template
class Base {
public:
    Base();
    friend class T;
};

Now this doesn\'t work... Is there a way of doing

相关标签:
3条回答
  • 2020-12-01 04:50

    It is explicitly disallowed in the standard, even if some versions of VisualStudio do allow it.

    C++ Standard 7.1.5.3 Elaborated type specifiers, paragraph 2

    3.4.4 describes how name lookup proceeds for the identifier in an elaborated-type-specifier. If the identifier resolves to a class-name or enum-name, the elaborated-type-specifier introduces it into the declaration the same way a simple-type-specifier introduces its type-name. If the identifier resolves to a typedef-name or a template type-parameter, the elaborated-type-specifier is ill-formed. [Note: this implies that, within a class template with a template type-parameter T, the declaration friend class T; is ill-formed. ]

    I recognize the code above as a pattern to seal (disallow the extension of) a class. There is another solution, that does not really block the extension but that will flag unadvertidly extending from the class. As seen in ADOBE Source Library:

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

    with the usage:

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

    While it allows extension if you really force it:

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

    It will restrict users from mistakenly do it.

    EDIT:

    The upcoming C++11 standard does allow you to befriend a type argument with a slightly different syntax:

    template <typename T>
    class A {
       // friend class T; // still incorrect: elaborate type specifier
       friend T;          // correct: simple specifier, note lack of "class"
    };
    
    0 讨论(0)
  • 2020-12-01 05:01

    I found a simple trick to declare template parameters as friends:

    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
    

    However I do not know how this could help to define an alternative version of a class sealer.

    0 讨论(0)
  • 2020-12-01 05:12

    Do you really need to do this? If you want to prevent someone from deriving from your class, just add a comment and make the destructor non-virtual.

    0 讨论(0)
提交回复
热议问题