Friendly classes defined in the std namespace: any guarantees?

This question arose as I answered this question : does the standard allow and make any guarantees regarding friend-ing standard library classes and / or functions?

In this particular case, the situation was the question:

class MyUserDefinedType
{
    friend struct std::default_delete<MyUserDefinedType>;

private:
    ~MyUserDefinedType() { }
}

guaranteed the ability to save MyUserDefinedTypein the object std::unique_ptr<MyUserDefinedType>or std::shared_ptr<MyUserDefinedType>with default default.

In general, the classes described in the standard library, necessary to implement their functionality directly or can use any arbitrary level of indirection? For example, is it possible that

  • std::default_delete<MyUserDefinedType> using , std, friend

  • std::default_delete<MyUserDefinedType> , , friend

- ?

, UB , , .

clang trunk (w/lib++) GCC 4.7.2 (w/libstd++), FWIW

+5
2

, std::default_delete<MyUserDefinedType> , std, ?

. 20.7.1.1.2 ++ 11:

namespace std {
    template <class T> struct default_delete {
        constexpr default_delete() noexcept = default;
        template <class U> default_delete(const default_delete<U>&) noexcept;
        void operator()(T*) const;
    };
}

, , . , . , .

, std::default_delete<MyUserDefinedType> , , ?

. , - . 20.1.1.2:

void operator()(T *ptr) const;

3 : delete ptr.

4 : T , .

, default_delete<>, ( - ).

+5

, , , ?

, . , , - , . , default_delete - , , , , .

, UB, , .

UB, .

, default_delete<MyUserDefinedType> ( ), .

, , . :

//your code
class MyUserDefinedType
{
    friend struct std::default_delete<MyUserDefinedType>; //for deletion
private:  
    int veryPrivateData;
    ~MyUserDefinedType() { }
};

//evil colleague code:
namespace std {
  //we may specialize std-templates for UDTs...
  template<>
  struct default_delete<MyUserDefinedType>
  {
    constexpr default_delete() noexcept = default;
    template <class U> default_delete(const default_delete<U>&) noexcept {}
    void operator()(T* pt) const { delete pt; }

    //sneaky...
    void access(MyUserDefinedType& mudt, int i) const
    { mudt.veryPrivateData = i; }
  };
}

void somewhere_deep_in_the_code()
{
  MyUserDefinedType& myUDT = /*something...*/;
  std::default_delete<MyUserDefinedType>().access(myUDT, 42); //tricked you!
}

- . . - , , .

+1

All Articles