Considerations for moving semantics for a type

I implement type T Although this is not a requirement, users of this type can use the movement semantics, i.e. T(T&&) and T& operator=(T&&) .

Since T contains std::function as element data, I cannot implement move semantics with noexcept guarantees, which would make T less useful to the user.

Also, for this reason, my implementation cannot be as simple as: T(&&) noexcept = default and T& operator=(T&&) noexcept = default

An alternative would be to offer the user a non- noexcept version: T(&&) = default and T& operator=(T&&) = default ; or implement my custom noexcept move semantics in terms of std::function::swap() (which is guaranteed to be noexcept ). In the latter case, unfortunately, I would have to take care of all other member data except std::function (ugly!).

So there are three options:

  • disable move semantics altogether
  • implement T(&&) = default and T& operator=(T&&) = default
  • implement your own T(&&) noexcept {/* lot of code */} and T& operator=(T&&) noexcept {/* lot of code */}

I know that the question is quite subjective, but what would you choose?

+5
source share
2 answers

Assuming you really want to move noexcept , you can reduce the number of templates for option # 3 either:

  • grouping elements not related to the position-noexcept-moveable into a nested member of a structure or private base class and the move-ctor entry that just moves it (one line for all of them) and then replaces std::function s or
  • Writing a wrapper for a SwapMove template to store a function in. It just needs to implement the ctor move and assignment operator using swap, and by default everything else. OK, you also need to either expose a function element or forward a function call statement.
+4
source

Why don't you try putting all your functions in std :: function inside std :: vector and then swap the vector?

vector has noexcept constructor for move.

EDIT:

To fully expand the necessary concepts, I can not answer in the comments.

For your situation (different function signatures), you will need to erase the styles and some dynamic clicks.

Here is some code that uses all of these concepts in the content (vector and enumeration and others).

Now you can save the vector of your lambdas, regardless of the signature.

 class LambdaContainer { public: struct GenericContainer { virtual ~GenericContainer(){} }; template <typename T> struct SpecializedContainer : GenericContainer { SpecializedContainer(const T& t) : lambda(t){} virtual ~SpecializedContainer(){} T lambda; }; private: std::shared_ptr<GenericContainer> myLambda; public: template <typename T> LambdaContainer(const T& aLambda) : myLambda(new SpecializedContainer<T>(aLambda)){} std::shared_ptr<GenericContainer> getContainedLambda() { return myLambda; } }; enum eFunctions { FCT_INT=0, FCT_FLOAT=1 }; ... int main() { int aa = 10; float b = 3.0f; std::function<void(int)> lambda1 = [aa](int arg) { printf("at this time b plus argument is %d\n ",aa+arg); }; std::function<int (float, float )> lambda2 = [b] (float arg1, float arg2) { printf("calling the sum of floats %f , %f\n"); return (int)(arg1+arg2+b);}; std::vector<LambdaContainer> lambdaVector; lambdaVector.push_back(LambdaContainer(lambda1)); lambdaVector.push_back(LambdaContainer(lambda2)); std::shared_ptr<LambdaContainer::GenericContainer> container = lambdaVector[FCT_INT].getContainedLambda(); LambdaContainer::SpecializedContainer<std::function<void(int)> >* ptr = dynamic_cast<LambdaContainer::SpecializedContainer<std::function<void(int)> >*> (container.get()); if (ptr!=NULL) { std::function<void(int)> extractedLambda = ptr->lambda; extractedLambda(5); } std::shared_ptr<LambdaContainer::GenericContainer> container2 = lambdaVector[FCT_FLOAT].getContainedLambda(); LambdaContainer::SpecializedContainer<std::function<int(float,float)> >* ptr2 = dynamic_cast<LambdaContainer::SpecializedContainer<std::function<int(float,float)> >*> (container2.get()); if (ptr2!=NULL) { std::function<int(float,float)> extractedLambda = ptr2->lambda; printf("the sum is %d\n",extractedLambda(3.0f,2.0f)); } 

}

0
source

All Articles