Changeset 10975 for code/branches/cpp11_v2
- Timestamp:
- Dec 23, 2015, 7:16:33 PM (9 years ago)
- Location:
- code/branches/cpp11_v2
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
code/branches/cpp11_v2/src/libraries/core/command/Functor.h
r10876 r10975 118 118 #include <array> 119 119 #include <typeindex> 120 #include <type_traits> 120 121 #include <tuple> 121 122 … … 303 304 304 305 protected: 305 /// Casts the object and registers as destruction listener. 306 /// Casts the object and registers as destruction listener if the object is a Destroyable. 307 template<bool = std::is_base_of<Destroyable, O>::value> 306 308 inline void registerObject(O* object) 307 { Destroyable* base = dynamic_cast<Destroyable*>(object); if (base) { this->registerAsDestructionListener(base); } } 308 /// Casts the object and unregisters as destruction listener. 309 { this->registerAsDestructionListener(static_cast<Destroyable*>(object)); } 310 311 template<> 312 inline void registerObject<false>(O* object) {} 313 314 /// Casts the object and unregisters as destruction listener if the object is a Destroyable. 315 template<bool = std::is_base_of<Destroyable, O>::value> 309 316 inline void unregisterObject(O* object) 310 { Destroyable* base = dynamic_cast<Destroyable*>(object); if (base) { this->unregisterAsDestructionListener(base); } } 311 312 /// Will be called by Destroyable::~Destroyable() if the stored object is deleted and the Functor is in safe mode. 317 { this->unregisterAsDestructionListener(static_cast<Destroyable*>(object)); } 318 319 template<> 320 inline void unregisterObject<false>(O* object) {} 321 322 /// Will be called by Destroyable::~Destroyable() if the stored object is a Destroyable and deleted and the Functor is in safe mode. 313 323 virtual inline void objectDeleted() override 314 324 { this->object_ = nullptr; } … … 450 460 @param O The class of the function 451 461 @param isconst True if the function is a const member-function 452 @param P1 The type of the first parameter 453 @param P2 The type of the second parameter 454 @param P3 The type of the third parameter 455 @param P4 The type of the fourth parameter 456 @param P5 The type of the fifth parameter 462 @param Params The types of the parameters 457 463 458 464 This template has many parameters and is usually not used directly. It is created by … … 566 572 }; 567 573 574 575 /** 576 @brief FunctorCallable is a child class of FunctorTemplate. It stores a callable 577 object (e.g. a lambda or a class with operator()) inside and acts like any 578 other functor. Note that it stores a \em copy of the object, not a reference or a pointer. 579 Take care that this functor does not outlive objects that have been captured by reference 580 in a lambda. 581 582 @param F The type of the callable object 583 @param R The type of the return-value of the function 584 @param isconst True if operator() is const 585 @param Params The types of the parameters 586 587 This template can not be used directly when using lambdas - the type of a lambda 588 is not specified. It can only really be used through the base-class Functor. 589 */ 590 template <class F, class R, bool isconst, class... Params> 591 class FunctorCallable : public FunctorTemplate<R, F, isconst, Params...> 592 { 593 public: 594 FunctorCallable(const F& obj): FunctorTemplate<R, F, isconst, Params...>(&F::operator(), &obj_) 595 , obj_(obj) 596 {} 597 598 private: 599 F obj_; ///< The callable object 600 }; 601 602 namespace detail 603 { 604 //Helper functions to deduce types and constness of operator() and return the correct FunctorCallable 605 template <class F, class R, class... Params> inline FunctorMemberPtr<F> callableHelper(const F& obj, R(F::*func)(Params...) const) { return std::make_shared<FunctorCallable<F, R, true, Params...>>(obj); } 606 template <class F, class R, class... Params> inline FunctorMemberPtr<F> callableHelper(const F& obj, R(F::*func)(Params...)) { return std::make_shared<FunctorCallable<F, R, false, Params...>>(obj); } 607 } 608 568 609 template <class R, class O, class OO, class... Params> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(Params...), OO* object) { return std::make_shared<FunctorTemplate<R, O, false, Params...>>(functionPointer, object); } ///< Creates a new FunctorMember with the given function-pointer and an assigned object 569 610 template <class R, class O, class OO, class... Params> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(Params...) const, OO* object) { return std::make_shared<FunctorTemplate<R, O, true, Params...>>(functionPointer, object); } ///< Creates a new FunctorMember with the given function-pointer and an assigned object … … 573 614 574 615 template <class R, class... Params> inline FunctorStaticPtr createFunctor(R (*functionPointer)(Params...)) { return std::make_shared<FunctorTemplate<R, void, false, Params...>>(functionPointer); } ///< Creates a new Functor with the given function-pointer 616 617 template <class F> inline FunctorMemberPtr<F> createFunctor(const F& obj) { return detail::callableHelper(obj, &F::operator()); } ///< Creates a new Functor with a callable object 575 618 } 576 619 -
code/branches/cpp11_v2/test/core/command/FunctorTest.cc
r10922 r10975 19 19 }; 20 20 21 class DestroyableClass : public Destroyable 22 { 23 public: 24 void method() {}; 25 }; 26 21 27 void f1(int, double) 22 28 { … … 31 37 return 0; 32 38 } 39 40 struct CallableStruct 41 { 42 public: 43 int operator()() 44 { 45 return 1; 46 } 47 }; 33 48 } 34 49 … … 38 53 FunctorPtr fp2 = createFunctor(&f2); 39 54 FunctorPtr fp3 = createFunctor(&f3); 40 ASSERT_ TRUE(fp1->getHeaderIdentifier(1) == fp2->getHeaderIdentifier(1));41 ASSERT_ TRUE(fp1->getHeaderIdentifier(2) == fp2->getHeaderIdentifier(2));42 ASSERT_ FALSE(fp1->getHeaderIdentifier(1) == fp2->getHeaderIdentifier(2));43 ASSERT_ FALSE(fp1->getHeaderIdentifier(10) == fp2->getHeaderIdentifier(10));44 ASSERT_ FALSE(fp2->getHeaderIdentifier(2) == fp3->getHeaderIdentifier(2));45 ASSERT_ FALSE(fp1->getHeaderIdentifier() == fp2->getHeaderIdentifier());46 ASSERT_ FALSE(fp2->getHeaderIdentifier() == fp3->getHeaderIdentifier());55 ASSERT_STREQ(fp1->getHeaderIdentifier(1).name(), fp2->getHeaderIdentifier(1).name()); 56 ASSERT_STREQ(fp1->getHeaderIdentifier(2).name(), fp2->getHeaderIdentifier(2).name()); 57 ASSERT_STRNE(fp1->getHeaderIdentifier(1).name(), fp2->getHeaderIdentifier(2).name()); 58 ASSERT_STRNE(fp1->getHeaderIdentifier(10).name(), fp2->getHeaderIdentifier(10).name()); 59 ASSERT_STRNE(fp2->getHeaderIdentifier(2).name(), fp3->getHeaderIdentifier(2).name()); 60 ASSERT_STRNE(fp1->getHeaderIdentifier().name(), fp2->getHeaderIdentifier().name()); 61 ASSERT_STRNE(fp2->getHeaderIdentifier().name(), fp3->getHeaderIdentifier().name()); 47 62 } 48 63 … … 52 67 FunctorPtr fp2 = createFunctor(&f2); 53 68 FunctorPtr fp3 = createFunctor(&f3); 54 ASSERT_ TRUE(fp1->getTypenameReturnvalue() ==fp2->getTypenameReturnvalue());55 ASSERT_ TRUE(fp1->getTypenameParam(0) ==fp3->getTypenameParam(0));69 ASSERT_EQ(fp1->getTypenameReturnvalue(), fp2->getTypenameReturnvalue()); 70 ASSERT_EQ(fp1->getTypenameParam(0), fp3->getTypenameParam(0)); 56 71 ASSERT_EQ("void", fp1->getTypenameReturnvalue()); 57 72 ASSERT_EQ("int", fp3->getTypenameReturnvalue()); … … 67 82 FunctorPtr fp3 = createFunctor(&f3); 68 83 ASSERT_EQ(3, fp2->getParamCount()); 69 ASSERT_ FALSE(fp1->getParamCount() ==fp3->getParamCount());84 ASSERT_NE(fp1->getParamCount(), fp3->getParamCount()); 70 85 ASSERT_FALSE(fp2->hasReturnvalue()); 71 86 ASSERT_TRUE(fp3->hasReturnvalue()); … … 86 101 ASSERT_TRUE(mttype.null()); 87 102 } 103 104 TEST_F(FunctorTest, canUseCallables) 105 { 106 int a = 0; 107 FunctorPtr fp1 = createFunctor(CallableStruct{}); 108 FunctorPtr fp2 = createFunctor([](bool val) { return val; }); 109 FunctorPtr fp3 = createFunctor([&a]() {return a++; }); 110 FunctorPtr fp4 = createFunctor([a]() {return a; }); 111 ASSERT_EQ(1, (*fp1)().get<int>()); 112 ASSERT_EQ(true, (*fp2)(true).get<bool>()); 113 ASSERT_EQ(0, (*fp3)().get<int>()); 114 ASSERT_EQ(1, a); 115 ASSERT_EQ(0, (*fp4)().get<int>()); 116 ASSERT_STREQ(fp1->getHeaderIdentifier().name(), fp3->getHeaderIdentifier().name()); 117 } 118 119 TEST_F(FunctorTest, SafeModeWorks) 120 { 121 DestroyableClass* testclass = new DestroyableClass(); 122 DestroyableClass* testclass2 = new DestroyableClass(); 123 FunctorPtr fp1 = createFunctor(&DestroyableClass::method, testclass); 124 fp1->setSafeMode(true); 125 FunctorPtr fp2 = createFunctor(&DestroyableClass::method, testclass); 126 fp2->setSafeMode(true); 127 FunctorPtr fp3 = createFunctor(&DestroyableClass::method, testclass); 128 fp2->setRawObjectPointer(testclass2); 129 130 ASSERT_NE(nullptr, fp1->getRawObjectPointer()); 131 ASSERT_NE(nullptr, fp2->getRawObjectPointer()); 132 ASSERT_NE(nullptr, fp3->getRawObjectPointer()); 133 testclass->destroy(); 134 ASSERT_EQ(nullptr, fp1->getRawObjectPointer()); 135 ASSERT_NE(nullptr, fp2->getRawObjectPointer()); 136 ASSERT_NE(nullptr, fp3->getRawObjectPointer()); 137 138 fp3->setRawObjectPointer(testclass2); 139 fp3->setSafeMode(true); 140 fp2->setSafeMode(false); 141 testclass2->destroy(); 142 ASSERT_NE(nullptr, fp2->getRawObjectPointer()); 143 ASSERT_EQ(nullptr, fp3->getRawObjectPointer()); 144 } 88 145 }
Note: See TracChangeset
for help on using the changeset viewer.