关于类型的移动语义的考虑

时间:2015-08-21 10:47:14

标签: c++ c++11

我正在实施一种类型T。虽然这不是必需的,但此类用户可能会受到移动语义的影响,即T(T&&)T& operator=(T&&)

由于T包含std::function作为成员数据,我无法使用noexcept保证实现移动语义,这会使T 更少对用户有用。

另外,由于上述原因,我的实施不能简单:T(&&) noexcept = defaultT& operator=(T&&) noexcept = default

另一种方法是向用户提供noexcept 版本:T(&&) = defaultT& operator=(T&&) = default;或者根据noexcept(保证为std::function::swap())实现用户定义的noexcept移动语义。在后一种情况下,遗憾的是我不得不处理std::function以外的所有其他成员数据(丑陋!)。

所以,有三个选择:

  1. 禁用所有移动语义
  2. 实施T(&&) = defaultT& operator=(T&&) = default
  3. 实施我自己的T(&&) noexcept {/* lot of code */}T& operator=(T&&) noexcept {/* lot of code */}
  4. 我知道这个问题相当主观,但你会选择什么?

2 个答案:

答案 0 :(得分:4)

假设您确实希望noexcept移动,您可以通过以下方式减少选项#3的样板数量:

  1. 将default-noexcept-moveable成员分组为嵌套的struct成员或私有基类,并编写一个move-ctor,它只移动它(所有这些成员都有一行),然后交换std::function s ,或
  2. 编写一个SwapMove模板包装器,用于存储function。它只需要使用swap实现move ctor和assignment操作符,并默认其他所有内容。好的,您还需要公开function成员或转发函数调用操作符。

答案 1 :(得分:0)

为什么不尝试将所有函数放在std :: vector中的std :: function中,然后交换向量?

vector有noexcept移动构造函数。

编辑:

为了完全扩展所需的概念,我无法在评论中回复。

对于您的情况(不同的功能签名),您将需要类型擦除和一些动态转换。

这里有一些代码,它们使用了所有陈述的概念(向量和枚举等)。

现在你可以保留你的lambda的矢量,无论签名如何。

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));
}

}

相关问题