Skip to content

Commit 768a803

Browse files
committed
feat(SAMPLE-027): add TimeSpan compound assignment operators
XNA 4.0's FuzzyLogic sample does `timeChasingThisMouse += gameTime.ElapsedGameTime;` in Tank.ChooseBehavior. C# synthesizes compound assignment from `operator +`, so .NET's TimeSpan does not declare `+=`/`-=` and neither did this port; C++ has no such synthesis, so the operators have to exist for the expression to compile. Both forward to Add/Subtract, which is what the value-returning `operator+`/`-` already do, so they inherit the same OverflowException behaviour rather than duplicating the range checks. This follows the existing Decimal::operator+= precedent for a compound assignment C# generates rather than declares. Six tests cover the in-place value, that the returned reference is the same object, that the result equals the value-returning operator it is built on, and the overflow path at both ends.
1 parent c51cd0c commit 768a803

3 files changed

Lines changed: 76 additions & 0 deletions

File tree

modules/core/include/System/TimeSpan.hpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,29 @@ namespace System {
577577
/** Adds @p t2 to this TimeSpan. */
578578
TimeSpan operator+(const TimeSpan &t2) const;
579579

580+
public:
581+
/**
582+
* @brief Adds @p t2 to this TimeSpan in place.
583+
*
584+
* C++ counterpart of the compound assignment C# synthesizes from
585+
* <c>operator +(TimeSpan, TimeSpan)</c>.
586+
*
587+
* @param t2 The interval to add.
588+
* @return A reference to this TimeSpan after the addition.
589+
*/
590+
TimeSpan &operator+=(const TimeSpan &t2);
591+
592+
/**
593+
* @brief Subtracts @p t2 from this TimeSpan in place.
594+
*
595+
* C++ counterpart of the compound assignment C# synthesizes from
596+
* <c>operator -(TimeSpan, TimeSpan)</c>.
597+
*
598+
* @param t2 The interval to subtract.
599+
* @return A reference to this TimeSpan after the subtraction.
600+
*/
601+
TimeSpan &operator-=(const TimeSpan &t2);
602+
580603
public:
581604
/** Multiplies this TimeSpan by scalar @p factor. */
582605
TimeSpan operator*(double factor) const;

modules/core/src/System/TimeSpan.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,18 @@ namespace System {
609609

610610
TimeSpan TimeSpan::operator+(const TimeSpan &t2) const { return Add(t2); }
611611

612+
TimeSpan &TimeSpan::operator+=(const TimeSpan &t2)
613+
{
614+
*this = Add(t2);
615+
return *this;
616+
}
617+
618+
TimeSpan &TimeSpan::operator-=(const TimeSpan &t2)
619+
{
620+
*this = Subtract(t2);
621+
return *this;
622+
}
623+
612624

613625
TimeSpan TimeSpan::operator*(double factor) const {
614626
if (std::isnan(factor)) {

modules/core/tests/System/TimeSpanTests.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -838,3 +838,44 @@ TEST(TimeSpanParseExact1943Tests, TheEscapeEdgeCasesAreRejectedAsDotNetRejectsTh
838838
EXPECT_FALSE(TimeSpan::TryParseExact("1", "hh\\", unused)); // trailing '\' is an error
839839
EXPECT_FALSE(TimeSpan::TryParseExact("01:30", "hh':'mm'", unused)); // unterminated quote
840840
}
841+
842+
TEST(TimeSpanTests, OperatorPlusAssign_AccumulatesInPlace) {
843+
TimeSpan total = TimeSpan::Zero;
844+
total += TimeSpan::FromSeconds(1.5);
845+
EXPECT_EQ(total.getTicksProperty(), 15000000LL);
846+
total += TimeSpan::FromSeconds(2.5);
847+
EXPECT_DOUBLE_EQ(total.getTotalSecondsProperty(), 4.0);
848+
// The result must equal the value-returning operator+ it is built on.
849+
EXPECT_EQ(total, TimeSpan::FromSeconds(1.5) + TimeSpan::FromSeconds(2.5));
850+
}
851+
852+
TEST(TimeSpanTests, OperatorPlusAssign_ReturnsReferenceToTheSameObject) {
853+
TimeSpan value = TimeSpan::FromSeconds(1.0);
854+
TimeSpan& returned = (value += TimeSpan::FromSeconds(1.0));
855+
EXPECT_EQ(&returned, &value);
856+
EXPECT_DOUBLE_EQ(value.getTotalSecondsProperty(), 2.0);
857+
}
858+
859+
TEST(TimeSpanTests, OperatorPlusAssign_OverflowsThroughAdd) {
860+
TimeSpan value = TimeSpan::MaxValue;
861+
EXPECT_THROW(value += TimeSpan(static_cast<longcs>(1)), System::OverflowException);
862+
}
863+
864+
TEST(TimeSpanTests, OperatorMinusAssign_SubtractsInPlace) {
865+
TimeSpan value = TimeSpan(5, 0, 0);
866+
value -= TimeSpan(2, 30, 0);
867+
EXPECT_EQ(value.getTicksProperty(), 90000000000LL);
868+
EXPECT_EQ(value, TimeSpan(5, 0, 0) - TimeSpan(2, 30, 0));
869+
}
870+
871+
TEST(TimeSpanTests, OperatorMinusAssign_ReturnsReferenceToTheSameObject) {
872+
TimeSpan value = TimeSpan::FromSeconds(3.0);
873+
TimeSpan& returned = (value -= TimeSpan::FromSeconds(1.0));
874+
EXPECT_EQ(&returned, &value);
875+
EXPECT_DOUBLE_EQ(value.getTotalSecondsProperty(), 2.0);
876+
}
877+
878+
TEST(TimeSpanTests, OperatorMinusAssign_OverflowsThroughSubtract) {
879+
TimeSpan value = TimeSpan::MinValue;
880+
EXPECT_THROW(value -= TimeSpan(static_cast<longcs>(1)), System::OverflowException);
881+
}

0 commit comments

Comments
 (0)