带有私有构造函数的对象的vector :: \ templates_back

时间:2022-02-22 04:15:39

I want my Timer objects to be created via Timer::create() only. For this purpose, I made the constructor private. However, I get a compiler error saying that "Timer::Timer(unsigned int)' is private" within the context of new_allocator.h. How can I solve this problem?

我希望我的Timer对象只能通过Timer :: create()创建。为此,我将构造函数设为私有。但是,我得到一个编译器错误,说“在新的all_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;

2 个解决方案

#1


13  

You probably should implement your own allocator, that will be friend to timer:

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

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

The simplest solution would be derive from std::allocator<Timer> reimplementing rebind to rebind to itself, so vector couldn't rebind allocator back to std::allocator and implement own construct to actually create Timers.

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

#2


9  

You can use transfer-of-friendship semantics to avoid having to have a specialized vector allocator. It's a bit like dependency injection of friendship. This is really quite simple. You create an empty class who's makes itself a friend of your class. But the default constructor is private, so only your class can create instances of it. But the class is still copyable, so it can be passed to anybody.

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

Your Timer constructor will be public, but it requires one of these objects as an argument. Therefore, only your class, or a function called by it, can create these objects directly (copies/moves will still work).

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

Here's how you could do that in your code (live example):

以下是您在代码中执行此操作的方法(实例):

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;

#1


13  

You probably should implement your own allocator, that will be friend to timer:

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

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

The simplest solution would be derive from std::allocator<Timer> reimplementing rebind to rebind to itself, so vector couldn't rebind allocator back to std::allocator and implement own construct to actually create Timers.

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

#2


9  

You can use transfer-of-friendship semantics to avoid having to have a specialized vector allocator. It's a bit like dependency injection of friendship. This is really quite simple. You create an empty class who's makes itself a friend of your class. But the default constructor is private, so only your class can create instances of it. But the class is still copyable, so it can be passed to anybody.

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

Your Timer constructor will be public, but it requires one of these objects as an argument. Therefore, only your class, or a function called by it, can create these objects directly (copies/moves will still work).

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

Here's how you could do that in your code (live example):

以下是您在代码中执行此操作的方法(实例):

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;