简体   繁体   中英

error: no matching function for call to default copy constructor?

I have a std::map container variable in my class that is populated with objects of my nested-class :

class Logger {
private:
//...
    class Tick{
        ///stores start and end of profiling
        uint32_t start, lastTick,total;
        /// used for total time
        boost::mutex mutexTotalTime;
        ///is the profiling object started profiling?
        bool started;
    public:
        Tick(){
            begin();
        }
        /*
        Tick(const Tick &t){
            start = t.start;
            lastTick = t.lastTick;
            total = t.total;
            started = t.started;
        }
        */
        uint32_t begin();
        uint32_t end();
        uint32_t tick(bool addToTotalTime = false);
        uint32_t addUp(uint32_t value);
        uint32_t getAddUp();

    };
    std::map<const std::string, Tick> profilers_;
//...
public:
//...
Logger::Tick & Logger::getProfiler(const std::string id)
{
    std::map<const std::string, Tick>::iterator it(profilers_.find(id));
    if(it != profilers_.end())
    {
        return it->second;
    }
    else
    {
        profilers_.insert(std::pair<const std::string, Tick>(id, Tick()));
        it = profilers_.find(id);
    }
    return it->second;
}
//...
};

the above code will not compile if I dont provide a copy constructor while I thought the default copy constructor should be already in place?! Am I missing any concept? thanks

The copy constructor may be generated for you only if all members of your class are copyable. In the case of Tick you have an object

boost::mutex mutexTotalTime;

which is not copyable, so the compiler will not generate the copy constructor. Observe that in your commented out copy constructor you do not copy the mutex - because you know you should not. The compiler does not know that.

As a side note, there is no need to explicitly say const for map keys:

std::map<const std::string, Tick> profilers_;

Map keys are always const, and your declaration is completely equivalent to

std::map<std::string, Tick> profilers_;

boost::mutex is non-copyable. Since Tick has one as a data member, this makes Tick also non-copyable. This in turn makes the map non-copyable.

So to make Logger copyable, you have to provide your own copy constructor and implement an appropriate duplication of profilers_ in it. Or, perhaps even more appropriately (thanks to @LightnessRacesInOrbit for the suggestion), provide an appropriate copy constructor for Tick instead.

The problem is that boost::mutex is not copyable. So if you don't provide a copy constructor, the compiler attempts the generate a default one. That default one needs to copy all of the members, but cannot copy boost::mutex, so it gives up. Your copy constructor does not copy the mutex. Instead it default initializes the new one, so this works.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM