4

私はこのコードを持っています:

template <typename T, void (*f)(T*)>
class callfn
{
  public:
  void operator()(T* obj) const
  {
    f(obj);
  }
};

void call(int* foo) {}

void test()
{
  callfn<int, call> fun;
  fun(1);
}

これはうまくいく傾向があります。ただし、このタイプcallfnはいたるところで使用されています。このように呼び出すことができれば、はるかに望ましいと思います。

callfn<call> fun;

代わりに、の型を変更せずに、型から型を推測できるようにテンプレートcallを配置することは可能ですか?callfnTf

4

2 に答える 2

2

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して特定のタイプのを作成したいのですが、 で関数ポインタを運ぶオーバーヘッドは必要ありません。たとえば、次のことを考慮してください。Tfvoid (*)(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*));

上記のソリューションの唯一の煩わしさは、入力callfnMObj2回の必要があることだと思います。それで、これはどうですか:

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 つの理由から、これは良いことではないと思います。

  1. mfree(たとえばvoid mfree(MObj*)と)のオーバーロードが異なる場合は機能しませんvoid mfree(Foo*)
  2. ユーザーは通常std::unique_ptr、インスタンス化と (最終的には) デリータで a の指定された型が表示されることを期待します。上記の 1 行目は型 ( MObj) を示していますが、2 行目は示していません。タイプが表示されないと、混乱する人もいるかもしれません。

上記の 2 番目の点については議論の余地があることに同意します (自動を使用すべきかの議論に似ています)。

于 2013-11-08T06:38:24.520 に答える
1

いいえ、構造体またはクラスのみの関数の引数を知る必要はありません.C ++ではテンプレート型推論があります。

論文n3602はこれに対処しているように見えるので、これを煩わしく思うのはあなただけではないようです (私も)。それが含まれるかどうかはわかりませんが、この論文は少なくとも他の人がそれについて考えていることを意味します. n6301は、非型テンプレート パラメーターに使用する冗長な型名を排除できます。

もう1つのこと(c ++ 14でも)はmake_unique、次の標準に含まれるものです。また、自分でコーディングするのもおそらく比較的簡単です。

私のコメントで指摘したように、これで何を達成しようとしているのか、また余分な型を書かなければならないことが実際に障壁なのかは不明です。

コメントで、これが a の削除機能を作成するために必要であることを明確にしたので、unique_ptr何が問題なのかわかりません。

std::unique_ptr<int,void(*)(int*)> ptr(int_ptr,deleter);
于 2013-11-08T05:28:10.100 に答える