0

SomeFunctionandSetArgを のより一般的なものに置き換えたいと思いboostます。bindと組み合わせて何かできそうですがlambda、方法がわかりません。

このコードは非常に単純ですが、これを置き換えたい理由は、 for23etc の引数が必要だからです。

template<class T>
struct SomeFunction
{
    T value;
    SomeFunction(T s)
        : value(s) {}

    void operator()(T& s)
    {
        s = value;
    }
};

template<class T>
SomeFunction<T> SetArg(T value)
{
    return SomeFunction<T>(value);
}

要求事項:

  • 関数オブジェクトを返す関数が必要です。
  • この関数オブジェクトを呼び出すと、パラメーターは参照によって渡されます。
  • この関数は、事前に設定された値に設定することにより、参照によって渡されたオブジェクトを変更します。
  • 上記のコードでは、事前設定された値が で値によって渡されますctorが、他の方法でも問題ありません。

次のコードは、使用方法を示しています。

void main()
{
    std::string t;
    SetArg(std::string("hello"))(t);
    assert(t == "hello");
}

いくつかのコンテキスト:

クラス のクライアント コードをテストしたいFoofunc1そのため、 の実装を自分のものに置き換えたいと思いますが、柔軟な方法で行います。

struct Foo
{
    virtual void func1(std::string& s)
    {
    }
};

struct MockFoo : public Foo {
    MOCK_METHOD1(func1, void(std::string&));
};

void ExampleTestCase::example()
{
  MockFoo f;
  std::string s;

  EXPECT_CALL(f, func1(_))
      .WillOnce(Invoke(SetArg(std::string("hello"))));

  f.func1(s);

  CPPUNIT_ASSERT_EQUAL(std::string("hello"), s);
}

Invoke は、関数または関数オブジェクトを取ります。itの新しい実装内でfunc1は、 によって返された関数オブジェクトが呼び出されSetArg、その引数が string に設定されます"hello"

Invoke は gmock/gtest の一部ですが、そうでSetArgはありません。

4

1 に答える 1

1

これが私が思いついたものです。ここoperator()では可能な移動セマンティクスから実際に恩恵を受けていないため、セッターの設定にはおそらく何らかの調整が必要になるでしょうが、今のところそれを理解することはできません.

また、これにより、利用できない可能性のある C++11 機能が多用されることに注意してください。

#include <string>
#include <iostream>
#include <tuple>

// set arbitrary values to 
template<typename... Args>
struct setter {
  // needed because we cannot use initializer lists as they require assignment
  setter(const std::tuple<Args&...>& t) : t(t) {}
  std::tuple<Args...> t;

  // again a template to trigger deduction again
  template<typename... Args2>
  void operator()(Args2&&... args) {
    t = std::make_tuple(args...);
  }
};

template<typename... Args>
setter<Args&...> create_setter(Args&... args) {
  return setter<Args&...>(std::tie(args...));
}

int main()
{
  int i = 0;
  long l = 1;
  std::string foo = "foo";

  auto s = create_setter(i, l, foo);

  s(23, 42, "bar");
  std::cout << i << std::endl;
  std::cout << l << std::endl;
  std::cout << foo << std::endl;

  return 0;
}
于 2011-10-19T01:12:21.907 に答える