7

I have the idea to do this:

namespace std {
    template<>
    class default_delete<IplImage> {
    public:
        void operator()(IplImage *ptr) const {
            cvReleaseImage(&ptr);
        }
    };
};

typedef std::shared_ptr<IplImage> IplImageObj;

I didn't really found much information whether it is supported that I specialise default_delete and whether shared_ptr also uses default_delete by default.

It works like intended with Clang 5.0.0.

So, is it supported?

What if the STL implementation has a different internal namespace? It wouldn't find my declaration then? But it should error about the declaration then.

Albert
  • 65,406
  • 61
  • 242
  • 386
  • Specialising `default_delete` is only allowed if it preserves the existing semantics. (Yes, that means it is allowed, but quite pointless) – R. Martinho Fernandes Nov 29 '13 at 10:40
  • @R.MartinhoFernandes: Why pointless? It is the default destruction policy used by `std::unique_ptr` when no deleter is specified. So this is another way of globally overriding the default destruction policy for some specific type used by `std::unique_ptr`. And I thought that the same applies but `shared_ptr`, and it does also in Clangs STL implementation, but it seems not according to the C++ standard. – Albert Nov 29 '13 at 11:01
  • It's pointless because you have to preserve the original semantics. This is not a way of globally overriding anything *because you are not allowed* to make a specialisation that doesn't do what the others do. – R. Martinho Fernandes Nov 29 '13 at 11:05
  • In other words, `std::default_delete` cannot mean different things in my program and in yours, and yet my program doesn't have a specialisation. It must mean the same in every C++ program. – R. Martinho Fernandes Nov 29 '13 at 11:14
  • @R.MartinhoFernandes: Ah, thanks, I see. Where does it say that I am only allowed to specialize `default_delete` if it preserves the existing semantics? – Albert Nov 29 '13 at 11:15
  • 3
    In 17.6.4.2.1. Also see: http://stackoverflow.com/a/8513497/46642 ("A program may add a template specialization for any standard library template to namespace std only if the declaration depends on a user-defined type and the specialization meets the standard library requirements for the original template and is not explicitly prohibited.") – R. Martinho Fernandes Nov 29 '13 at 11:16
  • 1
    @R.MartinhoFernandes: That just says that it has to meet the same requirements as the standard library, not that it needs to have the same semantics. Of course, the real problem is that `std::default_delete` is (only) for `std::unique_ptr`, not for `std::shared_ptr`... – Chris Dodd Jan 07 '14 at 02:38
  • I don't understand the distinction. The entire standard is a set of requirements on implementations. – R. Martinho Fernandes Jan 09 '14 at 13:16
  • Can anyone shed some light on what exactly is wrong with this specializing? – J. Doe Apr 22 '18 at 06:02
  • 1
    @R.MartinhoFernandes: I think ChrisDodd's point is that it has to behave in the expected way for deleters; preserving existing semantics means "behaving like a deleter", not "performing identical actions as the broken default you're trying to replace". As long as the API matches, it does what it's expected to do (perform appropriate cleanup for the type in question to avoid leaks), and only one overload is defined, it's allowed. There's no requirement that two unrelated programs have to agree on what deletion means. Still doesn't help `std::shared_ptr`, but useful for `std::unique_ptr`. – ShadowRanger Nov 21 '19 at 21:22

1 Answers1

4

default_delete should be defined in std namespace and it's ok to specialize entities from std namespace.

namespace std {
template<class T> struct default_delete;
template<class T> struct default_delete<T[]>;

However, your specialization violates some of the requirements of std::default_delete and thus is UB. Quotes about this thing are here (thanks to R. Martinho Fernandes).

However, shared_ptr is not specified to use default_delete.

~shared_ptr();

Effects:

  • If *this is empty or shares ownership with another shared_ptr instance (use_count() > 1), there are no side effects.

  • Otherwise, if *this owns an object p and a deleter d, d(p) is called.

  • Otherwise, *this owns a pointer p, and delete p is called.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
ForEveR
  • 55,233
  • 2
  • 119
  • 133
  • Ah, so then the Clang STL implementation is wrong about this? Because if I specialize `default_delete`, `shared_ptr` with no custom deleter would use my specialized `default_delete` and thus not necessarily call `delete p`. – Albert Nov 29 '13 at 11:03
  • Ah, according to MartinhoFernandes in the comments, I'm not allowed to specialize it (in my way). So then it doesn't really matters if `shared_ptr` uses it or not. – Albert Nov 29 '13 at 11:13
  • You should add a link to http://stackoverflow.com/a/8513497/46642 to explain why I'm not allowed to specialize `default_delete` the way I did. – Albert Nov 29 '13 at 11:24
  • 1
    @Albert: I'm not seeing how anything there prohibits specializing `std::default_delete`. I think MartinhoFernandes is reading "the specialization meets the standard library requirements for the original template" in a weirdly strict way; the standard library requirements are basically just "matches prototype (`void operator()(T* ptr) const;`), performs some logical deletion function", which your code meets (it's just that `std::shared_ptr` doesn't claim to use it). – ShadowRanger Nov 21 '19 at 21:28