aaronmanの投稿の上に追加します。テンプレート クラスだけではできませんが、マクロを含む一部のヘルパーを使用すると、次のことが可能になります。
template <typename T>
T deduce(void(*)(T*));
#define CALLFN(f) callfn<decltype(deduce(f)), f>
使用例:
CALLFN(call) fun; // instead of 'callfn<call> fun;' as asked
ただし、OPのコメントから、これは問題の一部に過ぎず、この部分を使用しないと解決策がより簡単に見えます。
私がそれを正しく理解していれば、(タイプの)カスタム関数デリータを使用std::unique_ptr
して特定のタイプのを作成したいのですが、 で関数ポインタを運ぶオーバーヘッドは必要ありません。たとえば、次のことを考慮してください。T
f
void (*)(T*)
std::unique_ptr
class MObj { /* ... */ };
void mfree(MObj*) { /* ... */ }
OPのコメントで述べたように、通常は
std::unique_ptr<MObj, void(*)(MObj*)> p1(nullptr, mfree);
assert(sizeof(p1) == sizeof(MObj*) * 2);
しかし、使用callfn
するとスペースを節約できます。
std::unique_ptr<MObj, callfn<MObj, mfree>> p2;
assert(sizeof(p2) == sizeof(MObj*));
上記のソリューションの唯一の煩わしさは、入力callfn
とMObj
2回の必要があることだと思います。それで、これはどうですか:
template <typename T, void (*f)(T*)>
using light_unique_ptr = std::unique_ptr<T, callfn<T, f>>;
light_unique_ptr<MObj, mfree> p3; // 1
assert(sizeof(p3) == sizeof(MObj*));
また、意図が次のようなさらに短いものを持っていることも理解しています(間違っているかもしれません)
lighter_unique_ptr<mfree> p4; // 2
assert(sizeof(p4) == sizeof(MObj*));
からポイントされたオブジェクトのタイプを推測するためにコンパイラを終了しますmfree
。前述したように、これはマクロで実行できますが、次の 2 つの理由から、これは良いことではないと思います。
mfree
(たとえばvoid mfree(MObj*)
と)のオーバーロードが異なる場合は機能しませんvoid mfree(Foo*)
。
- ユーザーは通常
std::unique_ptr
、インスタンス化と (最終的には) デリータで a の指定された型が表示されることを期待します。上記の 1 行目は型 ( MObj
) を示していますが、2 行目は示していません。タイプが表示されないと、混乱する人もいるかもしれません。
上記の 2 番目の点については議論の余地があることに同意します (自動を使用すべきかの議論に似ています)。