C++ vector::为具有私有构造函数的对象重新放置

C++ vector::为具有私有构造函数的对象重新放置,c++,c++11,constructor,C++,C++11,Constructor,我只希望通过Timer::create()创建计时器对象。为此,我将构造函数设置为私有。但是,我得到一个编译器错误,在new_allocator.h的上下文中“Timer::Timer(unsigned int)”是私有的。我怎样才能解决这个问题 class Timer { private: int timeLeft; Timer(unsigned int ms) : timeLeft(ms) {} public: static

我只希望通过Timer::create()创建计时器对象。为此,我将构造函数设置为私有。但是,我得到一个编译器错误,在new_allocator.h的上下文中“Timer::Timer(unsigned int)”是私有的。我怎样才能解决这个问题

class Timer {
    private:
        int timeLeft;
        Timer(unsigned int ms) : timeLeft(ms) {}

    public:
        static std::vector<Timer> instances;
        static void create(unsigned int ms) {
            instances.emplace_back(ms);
        }
};

std::vector<Timer> Timer::instances;
类计时器{
私人:
int timeLeft;
计时器(无符号整数毫秒):timeLeft(毫秒){}
公众:
静态std::向量实例;
静态无效创建(无符号整数毫秒){
实例:向后放置(ms);
}
};
std::vector Timer::instances;

您可能应该实现自己的分配器,它将是计时器的朋友:

class Timer {

    struct TimerAllocator: std::allocator<Timer>
    {
        template< class U, class... Args >
        void construct( U* p, Args&&... args )
        {
            ::new((void *)p) U(std::forward<Args>(args)...);
        }

        template< class U > struct rebind { typedef TimerAllocator other; };

    };
    friend class TimerAllocator;

    private:
        int timeLeft;

    Timer(unsigned int ms) : timeLeft(ms) 
    {}

    public:
        static std::vector<Timer, TimerAllocator> instances;
        static void create(unsigned int ms) {
            instances.emplace_back(ms);
        }
};

std::vector<Timer, Timer::TimerAllocator> Timer::instances;

int main()

{
    Timer::create(100);
}
类计时器{
结构TimerAllocator:std::allocator
{
模板<类别U,类别…参数>
无效构造(U*p、参数和…参数)
{
::新建((void*)p)U(标准::转发(args)…);
}
模板结构重新绑定{typedef TimerAllocator other;};
};
朋友级时间定位器;
私人:
int timeLeft;
计时器(无符号整数毫秒):timeLeft(毫秒)
{}
公众:
静态std::向量实例;
静态无效创建(无符号整数毫秒){
实例:向后放置(ms);
}
};
std::vector Timer::instances;
int main()
{
定时器::创建(100);
}

最简单的解决方案是从
std::allocator
重新实现
rebind
到重新绑定到自身,因此,
vector
无法将分配器重新绑定到
std::allocator
并实现自己的
构造
来实际创建
计时器。

您可以使用友谊语义转移来避免必须有一个专门的
vector
分配器。这有点像友谊的依赖注入。这真的很简单。您创建了一个空类,该类使自己成为您的类的朋友。但是默认构造函数是私有的,因此只有您的类可以创建它的实例。但该类仍然是可复制的,因此可以传递给任何人

您的
计时器
构造函数将是公共的,但它需要这些对象中的一个作为参数。因此,只有您的类或它调用的函数才能直接创建这些对象(复制/移动仍然有效)

下面是如何在代码()中实现这一点:

类时间朋友
{
公众:
TimerFriend(const TimerFriend&)=默认值;
TimerFriend&运算符=(const TimerFriend&)=默认值;
私人:
TimerFriend(){}
朋友类定时器;
}
班级计时器{
私人:
int timeLeft;
公众:
计时器(unsigned int ms,const TimerFriend&):timeLeft(ms){}
静态std::向量实例;
静态无效创建(无符号整数毫秒){
实例。向后放置(ms,TimerFriend());
}
};
std::vector Timer::instances;

当然,
push_back
之所以有效,唯一的原因是复制/移动构造函数是公共的。如果所有构造函数都是私有的,
emplace\u-back
push\u-back
都不起作用……或者你可以让
std::vector
成为你班上的
朋友。不太干净,但简单多了。@KonradRudolph,这并不简单:当然,我建议让vector成为朋友,如果它有效的话,但问题是vector不调用构造函数,分配器调用。交矢量朋友没有帮助。为什么不简单地
friend类std::allocator
?@leemes,因为没有保证,
std::allocator
将创建计时器本身,并且不会重新索引(或将构造委托给其他分配器)。事实上,在我的
gcc4.7.0
is中,它确实会被重新索引,因此使其成为friend也没有帮助。为什么不让所有
std::allocator
成为朋友呢?这样,重新绑定就不重要了。
class TimerFriend
{
public:
  TimerFriend(const TimerFriend&) = default;
  TimerFriend& operator =(const TimerFriend&) = default;

private:
  TimerFriend() {}

  friend class Timer;
}

class Timer {
    private:
        int timeLeft;

    public:
        Timer(unsigned int ms, const TimerFriend&) : timeLeft(ms) {}

        static std::vector<Timer> instances;
        static void create(unsigned int ms) {
            instances.emplace_back(ms, TimerFriend());
        }
};

std::vector<Timer> Timer::instances;