2

だから私は次のコードを持っています:

#include <iostream>

template <typename T>
class funcky
{
  public:
    funcky(char const* funcName, T func)
      : name(funcName), myFunc(func)
    {
    }

  //private:
    char const* name;
    T myFunc;
};

#if 0
int main(void)
{
  char const* out = "nothing";

  // requires template args
  funcky test("hello", [&](int x, int y) -> int
  {
    out = "YES";
    return x + y;
  });

  std::cout << test.name << " = " << test.myFunc(1, 2) << std::endl;
  std::cout << test.name << " = " << out << std::endl;

  return 0;
}

int main2(void)
{
  funcky<void(*)(void)> test("hello", [&, this](void) -> void
  {
    std::cout << this->name << std::endl;
  });

  test.myFunc();

  return 0;
}
#endif

int main(void)
{
  char const* out = "nothing";

  auto myFunc = [&](int x, int y) -> int
  {
    out = "YES";
    return x + y;
  };
  funcky<decltype(myFunc)> test("hello", myFunc);

  std::cout << test.name << " = " << test.myFunc(1, 2) << std::endl;
  std::cout << test.name << " = " << out << std::endl;

  return 0;
}

一番上のチャンクは、ラムダとその名前を保持する関数ホルダーです。

次はAPIに関して使用したいのですが、テンプレート引数が指定されていないため失敗します。

その後、特定のタイプ(funckyなど)の「this」を、その内部で宣言されていないラムダで使用できるかどうか疑問に思います。希望的観測。

最後に、コンパイルするが、funckyコンストラクターとdecltypeの外部でラムダを使用するコードがあります。

そのようなことはC++11で可能ですか?私はどのように言ったことを達成しますか?

また、同じAPIを使用できる場合を除いて、この方法で実行できないかのように、私が何をしているのかを推測しないようにしてください。簡単な方法で書き直します。努力する価値はありません。

4

2 に答える 2

3

ユーザーがクラスにコールバックを提供する方法を提供したい場合はstd::function、関数/ファンクタータイプでクラスをテンプレート化することは、経験したようにあまり便利ではないため、を使用することをお勧めします。

問題は、何も取り込めないという事実から生じます。後でどのように呼び出すかを知っておく必要があるため、コールバックとして渡すことができるものについて明確な要件を設定する必要があります。コンストラクターをテンプレートにする理由については、こちらをご覧ください。

#include <functional>
#include <utility>

struct X{
  template<class F>
  X(F&& f) : _callback(std::forward<F>(f)) {} // take anything and stuff it in the 'std::function'

private:
  std::function<int(int,int)> _callback;
};

int main(){
  X x([](int a, int b){ return a + b; });
}

ただし、コールバックがどのように呼び出されるかわからない場合たとえば、ユーザーが後で引数を渡す場合)、それをサポートしたい場合は、コールバックの署名でタイプをテンプレート化します。

#include <iostream>
#include <functional>
#include <utility>

template<class Signature>
struct X{
  template<class F>
  X(F&& f) : _callback(std::forward<F>(f)) {} // take anything and stuff it in the 'std::function'

private:
  std::function<Signature> _callback;
};

int main(){
  X<int(int,int)> x1([](int a, int b){ return a + b; });
  X<void()> x2([]{ std::cout << "wuzzah\n";});
}
于 2012-09-21T09:32:31.403 に答える
3

何かのようなもの

template<typename Functor>
funcky<typename std::decay<Functor>::type>
make_funcky(const char* name, Functor&& functor)
{ return { name, std::forward<Functor>(functor) }; }

次のような場合に役立ちます。

auto test = make_funcky("hello", [&](int x, int y) -> int
{
    out = "YES";
    return x + y;
});

ただし、ラムダ式の内部は常に式のすぐ外側をthis指します。thisこれは、呼び出し時に存在するものへの遅延参照ではありません。暗黙のパラメーターではありません。thisそのため、「別のタイプ」が必要なのは意味がありません。

于 2012-09-21T10:10:15.410 に答える