カスタムでリターを使用するユーザ定義型に対して std::unique_ptr を特殊化する

そんな話が Lingr の C++ 部屋で出ていたので。

// 毎回カスタムデリータを設定するのが手間
std::unique_ptr<X, decltype(&X_deleter)> xp(new X(42), &X_deleter);

// こう書けるようにしたい
// std::unique_ptr<X> xp(new X(42));

[コード]

#include <memory>
#include <iostream>


struct X{
    friend void X_deleter(X*);
    
    X(int value) : value(value){}
    int value;

private:
    ~X(){};
};

void
X_deleter(X* x){
    std::cout << "X_deleter" << std::endl;
    delete x;
}

namespace std{

template <>
struct unique_ptr<X, std::default_delete<X>> :unique_ptr<X, decltype(&X_deleter)>
{
    explicit unique_ptr(X* p)
        : unique_ptr<X, decltype(&X_deleter)>(p, &X_deleter) {}
};

}  // namespace std

int
main(){
//     std::unique_ptr<X, decltype(&X_deleter)> xp(new X(42), &X_deleter);
    std::unique_ptr<X> xp(new X(42));
    std::cout << xp->value << std::endl;
    
    return 0;
}

[出力]

42
X_deleter

一応、ユーザ定義型に対しての特殊化は許されているので仕様上は問題ないはず。
でもまぁ、特殊化するよりかはヘルパ関数を用意したほうがスマートだと思う。

template<typename... Args>
std::unique_ptr<X, decltype(&X_deleter)>
make_unique_X(Args... args){
    return { new X(args...), &X_deleter };
}

std::unique_ptr<X> xp(new X(42));