Skip to main content
added 383 characters in body
Source Link
G. Sliepen
  • 69.5k
  • 3
  • 75
  • 180

Since C++11, the standard library provides std::function, which basically does what your Event class does: store a function and any associated data you want captured. For example, your Event_CopyAssignment_EventRaised test can be rewritten like so:

#include <functional>
...
TEST_METHOD(Event_CopyAssignment_EventRaised) {
  int value;
  std::function<void(int, int)> event_two_param;
  int x{3}, y{2};

  using namespace std::placeholders;
  bool before = (bool)event_two_param;
  event_two_param = std::bind(OnEventTwoParam, _1, _2, std::ref(value));
  bool after = (bool)event_two_param;

  event_two_param(x, y);
  Assert::AreEqual(x + y, value);
  Assert::IsFalse(before);
  Assert::IsTrue(after);
}

Assigning the function to event_two_param such that it captures the reference to value is a bit awkward that way, but you can also use a lambda to do the same:

event_two_param = [&](int x, int y){ OnEventTwoParam(x, y, value); };

Or just use a lambda expression directly to sum two values:

event_two_param = [&](int x, int y){ value = x + y; };

Note that std::function also has an operator bool(), but it is marked explicit to avoid accidental conversion to bool, so you have to explicitly cast it if you want to use it like in your test. But you can use it without casting in an if-statement:

if (event_two_param) {
    /* event_two_param has a function associated with it */
    ...
}

std::function also solves all the issues you have mentioned: you can also use it for functions that don't take a pointer to userdata, and you can have it store functions that return a value:

std::function<int()> event_no_param;
event_no_param = []{ return 42; };
int value = event_no_param();
Assert::AreEqual(value, 42);

Since C++11, the standard library provides std::function, which basically does what your Event class does: store a function and any associated data you want captured. For example, your Event_CopyAssignment_EventRaised test can be rewritten like so:

#include <functional>
...
TEST_METHOD(Event_CopyAssignment_EventRaised) {
  int value;
  std::function<void(int, int)> event_two_param;
  int x{3}, y{2};

  using namespace std::placeholders;
  bool before = (bool)event_two_param;
  event_two_param = std::bind(OnEventTwoParam, _1, _2, std::ref(value));
  bool after = (bool)event_two_param;

  event_two_param(x, y);
  Assert::AreEqual(x + y, value);
  Assert::IsFalse(before);
  Assert::IsTrue(after);
}

Assigning the function to event_two_param such that it captures the reference to value is a bit awkward that way, but you can also use a lambda to do the same:

event_two_param = [&](int x, int y){ OnEventTwoParam(x, y, value); };

Or just use a lambda expression directly to sum two values:

event_two_param = [&](int x, int y){ value = x + y; };

Note that std::function also has an operator bool(), but it is marked explicit to avoid accidental conversion to bool, so you have to explicitly cast it if you want to use it like in your test. But you can use it without casting in an if-statement:

if (event_two_param) {
    /* event_two_param has a function associated with it */
    ...
}

Since C++11, the standard library provides std::function, which basically does what your Event class does: store a function and any associated data you want captured. For example, your Event_CopyAssignment_EventRaised test can be rewritten like so:

#include <functional>
...
TEST_METHOD(Event_CopyAssignment_EventRaised) {
  int value;
  std::function<void(int, int)> event_two_param;
  int x{3}, y{2};

  using namespace std::placeholders;
  bool before = (bool)event_two_param;
  event_two_param = std::bind(OnEventTwoParam, _1, _2, std::ref(value));
  bool after = (bool)event_two_param;

  event_two_param(x, y);
  Assert::AreEqual(x + y, value);
  Assert::IsFalse(before);
  Assert::IsTrue(after);
}

Assigning the function to event_two_param such that it captures the reference to value is a bit awkward that way, but you can also use a lambda to do the same:

event_two_param = [&](int x, int y){ OnEventTwoParam(x, y, value); };

Or just use a lambda expression directly to sum two values:

event_two_param = [&](int x, int y){ value = x + y; };

Note that std::function also has an operator bool(), but it is marked explicit to avoid accidental conversion to bool, so you have to explicitly cast it if you want to use it like in your test. But you can use it without casting in an if-statement:

if (event_two_param) {
    /* event_two_param has a function associated with it */
    ...
}

std::function also solves all the issues you have mentioned: you can also use it for functions that don't take a pointer to userdata, and you can have it store functions that return a value:

std::function<int()> event_no_param;
event_no_param = []{ return 42; };
int value = event_no_param();
Assert::AreEqual(value, 42);
added 383 characters in body
Source Link
G. Sliepen
  • 69.5k
  • 3
  • 75
  • 180

Since C++11, the standard library provides std::function, which basically does what your Event class does: store a function and any associated data you want captured. For example, your Event_CopyAssignment_EventRaised test can be rewritten like so:

#include <functional>
...
TEST_METHOD(Event_CopyAssignment_EventRaised) {
  int value;
  std::function<void(int, int)> event_two_param;
  int x{3}, y{2};

  using namespace std::placeholders;
  bool before = (bool)event_two_param;
  event_two_param = std::bind(OnEventTwoParam, _1, _2, std::ref(value));
  bool after = (bool)event_two_param;

  event_two_param(x, y);
  Assert::AreEqual(x + y, value);
  Assert::IsFalse(before);
  Assert::IsTrue(after);
}

Assigning the function to event_two_param such that it captures the reference to value is a bit awkward that way, but you can also use a lambda to do the same:

event_two_param = [&](int x, int y){ OnEventTwoParam(x, y, value); };

Or just use a lambda expression directly to sum two values:

event_two_param = [&](int x, int y){ value = x + y; };

Note that std::function also has an operator bool(), but it is marked explicit to avoid accidental conversion to bool, so you have to explicitly cast it if you want to use it like in your test. But you can use it without casting in an if-statement:

if (event_two_param) {
    /* event_two_param has a function associated with it */
    ...
}

Since C++11, the standard library provides std::function, which basically does what your Event class does: store a function and any associated data you want captured. For example, your Event_CopyAssignment_EventRaised test can be rewritten like so:

#include <functional>
...
TEST_METHOD(Event_CopyAssignment_EventRaised) {
  int value;
  std::function<void(int, int)> event_two_param;
  int x{3}, y{2};

  using namespace std::placeholders;
  bool before = event_two_param;
  event_two_param = std::bind(OnEventTwoParam, _1, _2, std::ref(value));
  bool after = event_two_param;

  event_two_param(x, y);
  Assert::AreEqual(x + y, value);
  Assert::IsFalse(before);
  Assert::IsTrue(after);
}

Assigning the function to event_two_param such that it captures the reference to value is a bit awkward that way, but you can also use a lambda to do the same:

event_two_param = [&](int x, int y){ OnEventTwoParam(x, y, value); };

Or just use a lambda expression directly to sum two values:

event_two_param = [&](int x, int y){ value = x + y; };

Since C++11, the standard library provides std::function, which basically does what your Event class does: store a function and any associated data you want captured. For example, your Event_CopyAssignment_EventRaised test can be rewritten like so:

#include <functional>
...
TEST_METHOD(Event_CopyAssignment_EventRaised) {
  int value;
  std::function<void(int, int)> event_two_param;
  int x{3}, y{2};

  using namespace std::placeholders;
  bool before = (bool)event_two_param;
  event_two_param = std::bind(OnEventTwoParam, _1, _2, std::ref(value));
  bool after = (bool)event_two_param;

  event_two_param(x, y);
  Assert::AreEqual(x + y, value);
  Assert::IsFalse(before);
  Assert::IsTrue(after);
}

Assigning the function to event_two_param such that it captures the reference to value is a bit awkward that way, but you can also use a lambda to do the same:

event_two_param = [&](int x, int y){ OnEventTwoParam(x, y, value); };

Or just use a lambda expression directly to sum two values:

event_two_param = [&](int x, int y){ value = x + y; };

Note that std::function also has an operator bool(), but it is marked explicit to avoid accidental conversion to bool, so you have to explicitly cast it if you want to use it like in your test. But you can use it without casting in an if-statement:

if (event_two_param) {
    /* event_two_param has a function associated with it */
    ...
}
Source Link
G. Sliepen
  • 69.5k
  • 3
  • 75
  • 180

Since C++11, the standard library provides std::function, which basically does what your Event class does: store a function and any associated data you want captured. For example, your Event_CopyAssignment_EventRaised test can be rewritten like so:

#include <functional>
...
TEST_METHOD(Event_CopyAssignment_EventRaised) {
  int value;
  std::function<void(int, int)> event_two_param;
  int x{3}, y{2};

  using namespace std::placeholders;
  bool before = event_two_param;
  event_two_param = std::bind(OnEventTwoParam, _1, _2, std::ref(value));
  bool after = event_two_param;

  event_two_param(x, y);
  Assert::AreEqual(x + y, value);
  Assert::IsFalse(before);
  Assert::IsTrue(after);
}

Assigning the function to event_two_param such that it captures the reference to value is a bit awkward that way, but you can also use a lambda to do the same:

event_two_param = [&](int x, int y){ OnEventTwoParam(x, y, value); };

Or just use a lambda expression directly to sum two values:

event_two_param = [&](int x, int y){ value = x + y; };