STLにはWILのout_param
に相当する機能がおそらく存在しませんが、簡単な構造体またはクラスを作成すれば同等の機能を得られます。
STLコンテナにまとめて作成する場合
std::pointer_traits
を利用します。ただし、MSVCでstd::pointer_traits
にポインタ以外を与えた場合はコンパイルエラーが発生します。
C++20から導入されるコンセプト(requires
)を使用していますが、コメントアウトすればC++17でも使用可能です。
#include <memory> template <typename T> requires std::constructible_from<std::pointer_traits<T>> struct stl_out_param { stl_out_param(T& p) : p1(p), p2(p.get()) {} ~stl_out_param() { p1.reset(p2); } constexpr operator element_type** () { return &p2; } private: typedef typename std::pointer_traits<T>::element_type element_type; T& p1; element_type* p2; }; template <typename T> requires std::constructible_from<std::pointer_traits<T>> constexpr stl_out_param<T> out_param(T& p) { return { p }; } void f(int** p) { *p = nullptr; } int main() { auto p1 = std::make_unique<int>(1); auto p2 = std::make_shared<int>(2); auto p3 = p2; f(out_param(p1)); f(out_param(p2)); return 0; }
STLコンテナ別に作成する場合
std::unique_ptr
、std::shared_ptr
に対してヘルパー関数、構造体を個別に定義するには以下のようにします。
#include <memory> template <typename T> struct unique_ptr_out_param { unique_ptr_out_param(std::unique_ptr<T>& p) : p1(p), p2(p.get()) {} ~unique_ptr_out_param() { p1.reset(p2); } constexpr operator T** () { return &p2; } private: std::unique_ptr<T>& p1; T* p2; }; template <typename T> inline constexpr unique_ptr_out_param<T> out_param(std::unique_ptr<T>& p) { return { p }; } template <typename T> struct shared_ptr_out_param { shared_ptr_out_param(std::shared_ptr<T>& p) : p1(p), p2(p.get()) {} ~shared_ptr_out_param() { p1.reset(p2); } constexpr operator T** () { return &p2; } private: std::shared_ptr<T>& p1; T* p2; }; template <typename T> constexpr shared_ptr_out_param<T> out_param(std::shared_ptr<T>& p) { return { p }; } void f(int** p) { *p = nullptr; } int main() { auto p1 = std::make_unique<int>(1); auto p2 = std::make_shared<int>(2); auto p3 = p2; f(out_param(p1)); // p1はnullptrを保持する。 f(out_param(p2)); // p2はnullptrを保持する。 // p3は変わらない。 return 0; }