c – 私有构造函数禁止使用emplace [_back]()来避免移动

前端之家收集整理的这篇文章主要介绍了c – 私有构造函数禁止使用emplace [_back]()来避免移动前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
请考虑以下代码
#include <vector>

class A
{
public:    
    A(A&&);  // somewhat expensive

    static std::vector<A> make_As()
    {
        std::vector<A> result;
        result.push_back(A(3));
        result.push_back(A(4));
        return result;
    }

private:
    A(int);  // private constructor
};

因为A的移动构造函数有点贵(无论什么原因),我想避免调用它并使用emplace_back():

#include <vector>

class A
{
public:    
    A(A&&);  // somewhat expensive

    static std::vector<A> make_As()
    {
        std::vector<A> result;
        result.emplace_back(3);
        result.emplace_back(4);
        return result;
    }

private:
    A(int);  // private constructor
};

不幸的是,使用emplace_back(),实际的构造函数调用是由标准库中的某些东西来完成的,它不具有足够的权限,能够调用A的私有构造函数.

我意识到可能没有什么可以做到这一点,但尽管如此,我觉得由于对emplace_back()的调用发生在A的成员之内,所以他们应该能够调用私有构造函数.

是否有任何解决方法

我唯一可以想到的是向A添加一个朋友声明,但需要A的朋友(即实际尝试调用构造函数的类)的精确类是实现特定的(例如,for GCC是__gnu_cxx :: new_allocator< A>).编辑:只是意识到这样的一个朋友的声明将允许任何人使用私有构造函数来构建一个A的容器,所以它不会真的解决任何东西,我也可以使构造函数在这一点上公开. .

更新:我应该补充说,A的移动构造函数是昂贵的,不是避免不必要调用它的唯一原因.可能A根本不可动(不可复制).当然,这不适用于矢量(因为emplace_back()可能需要重新分配矢量),但是它将使用deque,它也具有类似的emplace_back()方法,但不必重新分配任何东西.

解决方法

一个可能的解决方法(或kludge)将是使用助手类将参数保存到A的私有ctor(我们称之为EmplaceHelper类). EmplaceHelper还应该有一个私有的ctor,它应该与A相互的友谊.现在你需要的是一个公共的ctor,它使用这个EmplaceHelper(通过const-ref,可能),并使用emplace_back(EmplaceHelper(. ..)).

由于EmplaceHelper只能由A构建,因此您的公用ctor仍然是私有的.

甚至可能用一个模板化的EmplaceHelper来推广这个想法(可能使用std :: tuple来保存ctor参数).

编辑:实际上,似乎我简化了这个作为GMANNickG下面的评论给了我一个更简单的想法:EmplaceHelper可能只是一个空的类(仍然与私人ctor,与A的友情如上),但它不需要存储所有的ctor参数,只需修改您的私有ctor,将EmplaceHelper作为第一个(或最后一个)参数(并使其公开).效果与上述相同,但在EmplaceHelper中没有复杂的逻辑.

喜欢这个:

class A 
{ 
private:
    struct private_key {};

public:     
    A(int x,const private_key&) :
    A(x) // C++11 only,delegating constructor
    {}

    A(A&&);  // somewhat expensive 

    static std::vector<A> make_As() 
    { 
        std::vector<A> result; 
        result.emplace_back(3,private_key()); 
        result.emplace_back(4,private_key()); 
        return result; 
    } 

private: 
    A(int);  // private constructor 
};

如果委托构造函数不可用,您可以将每个版本的公共代码解除,或者完全摆脱A(int),并且只能使用新版本,可能使用默认的第二个参数.

猜你在找的C&C++相关文章