Changeset 10986
- Timestamp:
- Dec 28, 2015, 6:57:26 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
r10985 r10986 357 357 358 358 /** 359 @brief FunctorPointer is a child class of FunctorMember and ex pands it with a function-pointer.360 @param F The type of the function-pointer 361 @param O The type of the function's class (or void if it's a static function )359 @brief FunctorPointer is a child class of FunctorMember and extends it with a function-pointer (or a function-object). 360 @param F The type of the function-pointer (or the function-object) 361 @param O The type of the function's class (or void if it's a static function or a function-object) 362 362 363 363 The template FunctorPointer has an additional template parameter that defines the type 364 of the function-pointer . This can be handy if you want to get or set the function-pointer.365 You can then use a static_cast to cast a Functor to FunctorPointer if you know the type366 of the function-pointer.364 of the function-pointer (or the function-object). This can be handy if you want to get 365 or set the function-pointer (or the function-object). You can then use a static_cast 366 to cast a Functor to FunctorPointer if you know the type of the function. 367 367 368 368 However FunctorPointer is not aware of the types of the different parameters or the … … 383 383 { return this->functionPointer_; } 384 384 385 // see Functor::getFullIdentifier()386 virtual const std::type_info& getFullIdentifier() const override387 { return typeid(F); }388 389 385 protected: 390 386 F functionPointer_; ///< The stored function-pointer … … 393 389 namespace detail 394 390 { 395 // Helper class to get the type of the function pointer with the given class, parameters, return-value, and constness 396 template <class R, class O, bool isconst, class... Params> struct FunctionPointer { typedef R (O::*Type)(Params...); }; 397 template <class R, class O, class... Params> struct FunctionPointer<R, O, true, Params...> { typedef R (O::*Type)(Params...) const; }; 398 template <class R, class... Params> struct FunctionPointer<R, void, false, Params...> { typedef R (*Type)(Params...); }; 399 400 // Helper class, used to call a function-pointer with a given object and parameters and to return its return-value (if available) 401 template <class R, class O, bool isconst, class... Params> struct FunctorCaller { template <class... UnusedParams> static inline MultiType call(typename detail::FunctionPointer<R, O, isconst, Params...>::Type functionPointer, O* object, const Params&... parameters, const UnusedParams&...) { return (object->*functionPointer)(parameters...); } }; 402 template <class O, bool isconst, class... Params> struct FunctorCaller<void, O, isconst, Params...> { template <class... UnusedParams> static inline MultiType call(typename detail::FunctionPointer<void, O, isconst, Params...>::Type functionPointer, O* object, const Params&... parameters, const UnusedParams&...) { (object->*functionPointer)(parameters...); return MultiType::Null; } }; 403 template <class R, bool isconst, class... Params> struct FunctorCaller<R, void, isconst, Params...> { template <class... UnusedParams> static inline MultiType call(typename detail::FunctionPointer<R, void, isconst, Params...>::Type functionPointer, void*, const Params&... parameters, const UnusedParams&...) { return (*functionPointer)(parameters...); } }; 404 template <bool isconst, class... Params> struct FunctorCaller<void, void, isconst, Params...> { template <class... UnusedParams> static inline MultiType call(typename detail::FunctionPointer<void, void, isconst, Params...>::Type functionPointer, void*, const Params&... parameters, const UnusedParams&...) { (*functionPointer)(parameters...); return MultiType::Null; } }; 391 // Helper class to get the type of the function-pointer (or the function-object) with the given class, parameters, return-value, and constness 392 template <class F, class R, class O, bool isconst, class... Params> struct FunctionType /* generic type is undefined */; 393 template < class R, class O, class... Params> struct FunctionType<void, R, O, false, Params...> { typedef R (O::*Type)(Params...); }; // spezialization: non-const member function 394 template < class R, class O, class... Params> struct FunctionType<void, R, O, true, Params...> { typedef R (O::*Type)(Params...) const; }; // spezialization: const member function 395 template < class R, class... Params> struct FunctionType<void, R, void, false, Params...> { typedef R (*Type)(Params...); }; // spezialization: static function 396 template <class F, class R, class... Params> struct FunctionType<F, R, void, false, Params...> { typedef F Type; }; // spezialization: function object 397 398 // Helper class, used to call a function with a given object and parameters and to return its return-value (if available) 399 template <class F, class R, class O, bool isconst, class... Params> struct FunctorCaller /* generic type is undefined */; 400 template < class R, class O, bool isconst, class... Params> struct FunctorCaller<void, R, O, isconst, Params...> { template <class... UnusedParams> static inline MultiType call(typename detail::FunctionType<void, R, O, isconst, Params...>::Type functionPointer, O* object, const Params&... parameters, const UnusedParams&...) { return (object->*functionPointer)(parameters...); } }; // spezialization: member function with return value 401 template < class O, bool isconst, class... Params> struct FunctorCaller<void, void, O, isconst, Params...> { template <class... UnusedParams> static inline MultiType call(typename detail::FunctionType<void, void, O, isconst, Params...>::Type functionPointer, O* object, const Params&... parameters, const UnusedParams&...) { (object->*functionPointer)(parameters...); return MultiType::Null; } }; // spezialization: member function without return value 402 template < class R, class... Params> struct FunctorCaller<void, R, void, false, Params...> { template <class... UnusedParams> static inline MultiType call(typename detail::FunctionType<void, R, void, false, Params...>::Type functionPointer, void*, const Params&... parameters, const UnusedParams&...) { return (*functionPointer)(parameters...); } }; // spezialization: static function with return value 403 template < class... Params> struct FunctorCaller<void, void, void, false, Params...> { template <class... UnusedParams> static inline MultiType call(typename detail::FunctionType<void, void, void, false, Params...>::Type functionPointer, void*, const Params&... parameters, const UnusedParams&...) { (*functionPointer)(parameters...); return MultiType::Null; } }; // spezialization: static function without return value 404 template <class F, class R, class... Params> struct FunctorCaller<F, R, void, false, Params...> { template <class... UnusedParams> static inline MultiType call(typename detail::FunctionType<F, R, void, false, Params...>::Type functor, void*, const Params&... parameters, const UnusedParams&...) { return functor(parameters...); } }; // spezialization: function object with return value 405 template <class F, class... Params> struct FunctorCaller<F, void, void, false, Params...> { template <class... UnusedParams> static inline MultiType call(typename detail::FunctionType<F, void, void, false, Params...>::Type functor, void*, const Params&... parameters, const UnusedParams&...) { functor(parameters...); return MultiType::Null; } }; // spezialization: function object without return value 405 406 406 407 // Helper class to determine if a function has a returnvalue … … 457 458 that need to know the exact types of the parameters, return-value, and class. 458 459 460 @param F the type of the function-object (or void if a function-pointer is used). 459 461 @param R The type of the return-value of the function 460 462 @param O The class of the function … … 469 471 All template arguments can be void. 470 472 */ 471 template <class R, class O, bool isconst, class... Params>472 class FunctorTemplate : public FunctorPointer<typename detail::Function Pointer<R, O, isconst, Params...>::Type, O>473 template <class F, class R, class O, bool isconst, class... Params> 474 class FunctorTemplate : public FunctorPointer<typename detail::FunctionType<F, R, O, isconst, Params...>::Type, O> 473 475 { 474 476 static_assert(sizeof...(Params) <= 5, "Only up to 5 parameters are supported"); … … 476 478 public: 477 479 /// Constructor: Initializes the base class. 478 FunctorTemplate(typename detail::Function Pointer<R, O, isconst, Params...>::Type functionPointer, O* object = nullptr) : FunctorPointer<typename detail::FunctionPointer<R, O, isconst, Params...>::Type, O>(functionPointer, object) {}480 FunctorTemplate(typename detail::FunctionType<F, R, O, isconst, Params...>::Type functionPointer, O* object = nullptr) : FunctorPointer<typename detail::FunctionType<F, R, O, isconst, Params...>::Type, O>(functionPointer, object) {} 479 481 480 482 // see FunctorMember::operator()() 481 483 virtual MultiType operator()(O* object, const MultiType& param1 = MultiType::Null, const MultiType& param2 = MultiType::Null, const MultiType& param3 = MultiType::Null, const MultiType& param4 = MultiType::Null, const MultiType& param5 = MultiType::Null) override 482 484 { 483 return detail::FunctorCaller< R, O, isconst, Params...>::call(this->functionPointer_, object, param1, param2, param3, param4, param5);485 return detail::FunctorCaller<F, R, O, isconst, Params...>::call(this->functionPointer_, object, param1, param2, param3, param4, param5); 484 486 } 485 487 … … 535 537 } 536 538 539 // see Functor::getFullIdentifier() 540 virtual const std::type_info& getFullIdentifier() const override 541 { 542 return typeid(typename detail::FunctionType<void, R, O, isconst, Params...>::Type); 543 } 544 537 545 // see Functor::getHeaderIdentifier() 538 546 virtual const std::type_info& getHeaderIdentifier() const override 539 547 { 540 return typeid(typename detail::Function Pointer<R, void, false, Params...>::Type);548 return typeid(typename detail::FunctionType<void, R, void, false, Params...>::Type); 541 549 } 542 550 … … 560 568 const std::type_info& getTypelistIdentifier(detail::type_list<Types...>) const 561 569 { 562 return typeid(typename detail::Function Pointer<R, void, false, Types...>::Type);570 return typeid(typename detail::FunctionType<void, R, void, false, Types...>::Type); 563 571 } 564 572 }; 565 573 566 574 567 /**568 @brief FunctorCallable is a child class of FunctorTemplate. It stores a callable569 object (e.g. a lambda or a class with operator()) inside and acts like any570 other functor. Note that it stores a \em copy of the object, not a reference or a pointer.571 Take care that this functor does not outlive objects that have been captured by reference572 in a lambda.573 574 @param F The type of the callable object575 @param R The type of the return-value of the function576 @param isconst True if operator() is const577 @param Params The types of the parameters578 579 This template can not be used directly when using lambdas - the type of a lambda580 is not specified. It can only really be used through the base-class Functor.581 */582 template <class F, class R, bool isconst, class... Params>583 class FunctorCallable : public FunctorTemplate<R, F, isconst, Params...>584 {585 public:586 FunctorCallable(const F& obj): FunctorTemplate<R, F, isconst, Params...>(&F::operator(), &obj_)587 , obj_(obj)588 {}589 590 private:591 F obj_; ///< The callable object592 };593 594 575 namespace detail 595 576 { 596 577 //Helper functions to deduce types and constness of operator() and return the correct FunctorCallable 597 template <class F, class R, class... Params> inline Functor MemberPtr<F> callableHelper(const F& obj, R(F::*func)(Params...) const) { return std::make_shared<FunctorCallable<F, R, true, Params...>>(obj); }598 template <class F, class R, class... Params> inline Functor MemberPtr<F> callableHelper(const F& obj, R(F::*func)(Params...)) { return std::make_shared<FunctorCallable<F, R, false, Params...>>(obj); }578 template <class F, class R, class... Params> inline FunctorStaticPtr callableHelper(const F& functionObject, R(F::*)(Params...)) { return std::make_shared<FunctorTemplate<F, R, void, false, Params...>>(functionObject); } 579 template <class F, class R, class... Params> inline FunctorStaticPtr callableHelper(const F& functionObject, R(F::*)(Params...) const) { return std::make_shared<FunctorTemplate<F, R, void, false, Params...>>(functionObject); } // note: both const and non-const function-objects are treated as static functors with isconst=false. 599 580 } 600 581 601 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 602 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 603 604 template <class R, class O, class... Params> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(Params...)) { return std::make_shared<FunctorTemplate<R, O, false, Params...>>(functionPointer); } ///< Creates a new FunctorMember with the given function-pointer 605 template <class R, class O, class... Params> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(Params...) const) { return std::make_shared<FunctorTemplate<R, O, true, Params...>>(functionPointer); } ///< Creates a new FunctorMember with the given function-pointer 606 607 template <class R, class... Params> inline FunctorStaticPtr createFunctor(R (*functionPointer)(Params...)) { return std::make_shared<FunctorTemplate<R, void, false, Params...>>(functionPointer); } ///< Creates a new FunctorStatic with the given function-pointer 608 609 template <class F> inline FunctorMemberPtr<F> createFunctor(const F& obj) { return detail::callableHelper(obj, &F::operator()); } ///< Creates a new Functor with a callable object 582 template <class R, class O, class OO, class... Params> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(Params...), OO* object) { return std::make_shared<FunctorTemplate<void, R, O, false, Params...>>(functionPointer, object); } ///< Creates a new FunctorMember with the given function-pointer and an assigned object 583 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<void, R, O, true, Params...>>(functionPointer, object); } ///< Creates a new FunctorMember with the given function-pointer and an assigned object 584 585 template <class R, class O, class... Params> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(Params...)) { return std::make_shared<FunctorTemplate<void, R, O, false, Params...>>(functionPointer); } ///< Creates a new FunctorMember with the given function-pointer 586 template <class R, class O, class... Params> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(Params...) const) { return std::make_shared<FunctorTemplate<void, R, O, true, Params...>>(functionPointer); } ///< Creates a new FunctorMember with the given function-pointer 587 588 template <class R, class... Params> inline FunctorStaticPtr createFunctor(R (*functionPointer)(Params...)) { return std::make_shared<FunctorTemplate<void, R, void, false, Params...>>(functionPointer); } ///< Creates a new FunctorStatic with the given function-pointer 589 590 /** Take care that this functor does not outlive objects that have been captured by reference in a lambda. */ 591 template <class F> inline FunctorStaticPtr createFunctor(const F& functionObject) { return detail::callableHelper(functionObject, &F::operator()); } ///< Creates a new Functor with a callable object 610 592 } 611 593 -
code/branches/cpp11_v2/test/core/command/FunctorTest.cc
r10984 r10986 71 71 int f4a(int arg) { return arg*2; } 72 72 int f4b(int arg) { return arg*3; } 73 int multiply(int a, int b) { return a*b; } 73 74 74 75 struct CallableStruct … … 634 635 ////////////////////////////// Various tests ////////////////////////////// 635 636 637 TEST_F(FunctorTest, CreateFunctorWithVariousFunctionTypes) 638 { 639 FunctorPtr c1 = createFunctor(&f4a); 640 FunctorPtr c2 = createFunctor(&f4b); 641 FunctorPtr c3 = createFunctor([] (int arg) { return arg*4; }); 642 auto lambda = [] (int arg1, int arg2) { return arg1*arg2; }; 643 FunctorPtr c4 = createFunctor(lambda); 644 645 std::function<int()> bind0 = std::bind(multiply, 4, 6); 646 std::function<int(int)> bind1 = std::bind(multiply, std::placeholders::_1, 7); 647 std::function<int(int, int)> bind2 = std::bind(multiply, std::placeholders::_1, std::placeholders::_2); 648 std::function<int(int)> function = f4a; 649 650 FunctorPtr c5 = createFunctor(bind0); 651 FunctorPtr c6 = createFunctor(bind1); 652 FunctorPtr c7 = createFunctor(bind2); 653 FunctorPtr c8 = createFunctor(function); 654 655 656 EXPECT_EQ(8, (*c1)(4).get<int>()); 657 EXPECT_EQ(12, (*c2)(4).get<int>()); 658 EXPECT_EQ(16, (*c3)(4).get<int>()); 659 EXPECT_EQ(20, (*c4)(4, 5).get<int>()); 660 EXPECT_EQ(24, (*c5)(4).get<int>()); 661 EXPECT_EQ(28, (*c6)(4).get<int>()); 662 EXPECT_EQ(32, (*c7)(4, 8).get<int>()); 663 EXPECT_EQ(8, (*c8)(4).get<int>()); 664 665 EXPECT_EQ(1, c1->getParamCount()); 666 EXPECT_EQ(1, c2->getParamCount()); 667 EXPECT_EQ(1, c3->getParamCount()); 668 EXPECT_EQ(2, c4->getParamCount()); 669 EXPECT_EQ(0, c5->getParamCount()); 670 EXPECT_EQ(1, c6->getParamCount()); 671 EXPECT_EQ(2, c7->getParamCount()); 672 EXPECT_EQ(1, c8->getParamCount()); 673 674 EXPECT_EQ(typeid(int(*)(int)), c1->getFullIdentifier()); 675 EXPECT_EQ(typeid(int(*)(int)), c2->getFullIdentifier()); 676 EXPECT_EQ(typeid(int(*)(int)), c3->getFullIdentifier()); 677 EXPECT_EQ(typeid(int(*)(int, int)), c4->getFullIdentifier()); 678 EXPECT_EQ(typeid(int(*)()), c5->getFullIdentifier()); 679 EXPECT_EQ(typeid(int(*)(int)), c6->getFullIdentifier()); 680 EXPECT_EQ(typeid(int(*)(int, int)), c7->getFullIdentifier()); 681 EXPECT_EQ(typeid(int(*)(int)), c8->getFullIdentifier()); 682 683 EXPECT_EQ(typeid(int(*)(int)), c1->getHeaderIdentifier()); 684 EXPECT_EQ(typeid(int(*)(int)), c2->getHeaderIdentifier()); 685 EXPECT_EQ(typeid(int(*)(int)), c3->getHeaderIdentifier()); 686 EXPECT_EQ(typeid(int(*)(int, int)), c4->getHeaderIdentifier()); 687 EXPECT_EQ(typeid(int(*)()), c5->getHeaderIdentifier()); 688 EXPECT_EQ(typeid(int(*)(int)), c6->getHeaderIdentifier()); 689 EXPECT_EQ(typeid(int(*)(int, int)), c7->getHeaderIdentifier()); 690 EXPECT_EQ(typeid(int(*)(int)), c8->getHeaderIdentifier()); 691 692 EXPECT_EQ(typeid(int(*)(int)), c1->getHeaderIdentifier(1)); 693 EXPECT_EQ(typeid(int(*)(int)), c2->getHeaderIdentifier(1)); 694 EXPECT_EQ(typeid(int(*)(int)), c3->getHeaderIdentifier(1)); 695 EXPECT_EQ(typeid(int(*)(int)), c4->getHeaderIdentifier(1)); 696 EXPECT_EQ(typeid(int(*)()), c5->getHeaderIdentifier(1)); 697 EXPECT_EQ(typeid(int(*)(int)), c6->getHeaderIdentifier(1)); 698 EXPECT_EQ(typeid(int(*)(int)), c7->getHeaderIdentifier(1)); 699 EXPECT_EQ(typeid(int(*)(int)), c8->getHeaderIdentifier(1)); 700 701 EXPECT_EQ(typeid(int(*)()), c1->getHeaderIdentifier(0)); 702 EXPECT_EQ(typeid(int(*)()), c2->getHeaderIdentifier(0)); 703 EXPECT_EQ(typeid(int(*)()), c3->getHeaderIdentifier(0)); 704 EXPECT_EQ(typeid(int(*)()), c4->getHeaderIdentifier(0)); 705 EXPECT_EQ(typeid(int(*)()), c5->getHeaderIdentifier(0)); 706 EXPECT_EQ(typeid(int(*)()), c6->getHeaderIdentifier(0)); 707 EXPECT_EQ(typeid(int(*)()), c7->getHeaderIdentifier(0)); 708 EXPECT_EQ(typeid(int(*)()), c8->getHeaderIdentifier(0)); 709 } 710 711 TEST_F(FunctorTest, CanCallFunctorWithLambdaWichIsAlreadyOutOfScope) 712 { 713 int var1 = 1; 714 FunctorPtr fp1a = createFunctor([&var1] () { return var1++; }); 715 FunctorPtr fp1b = createFunctor([&var1] () { return var1; }); 716 FunctorPtr fp2; 717 FunctorPtr fp3; 718 719 { 720 int var2 = 2; 721 fp2 = createFunctor([var2] () { return var2; }); 722 } 723 { 724 int var3 = 3; 725 fp3 = createFunctor([var3] () { return var3; }); 726 } 727 728 EXPECT_EQ(1, var1); 729 EXPECT_EQ(1, (*fp1a)().get<int>()); 730 EXPECT_EQ(2, var1); 731 EXPECT_EQ(2, (*fp1b)().get<int>()); 732 733 EXPECT_EQ(2, (*fp2)().get<int>()); 734 EXPECT_EQ(3, (*fp3)().get<int>()); 735 } 736 636 737 TEST_F(FunctorTest, canCompareHeaderIdentifiers) 637 738 {
Note: See TracChangeset
for help on using the changeset viewer.