Franko Leon Tokalić
Franko Leon Tokalić

Reputation: 1508

Cannot make an object uncopyable

I'm making a server interface for network programming and I ran into a problem. I want to make a server object uncopyable, mostly because it doesn't really make sense to do so and would probably make problems, and also because it uses threads which can't be copied. However, when I make the copy constructor and assignment operator private, I get an error:

Error   2   error C2248: '(namespaces..)::Server::Server' : cannot access private member declared in class '(namespaces..)::Server' (path..)\type_traits    1545    1   Server

The error seems to be in the type_traits file? I haven't used it at all, though it might be possible that some of the other std files I'm including use it? I'm using iostream, sstream, string, thread, map.

Here's the server class definition:

class DLL_PUBLIC Server
{
public:
    Server(unsigned int);
    ~Server();

    (...)
private:
    class PvtImpl; //Private implementation, so it isn't seen in the header file
    PvtImpl *pvtImpl;

    Server(const Server &par_other){}
    Server& operator=(const Server &par_other){ return *this; }

    (...)
};

and the private implementation:

class Server::PvtImpl
{
public:
    bool running;
    unsigned int port, backlog, currentlyConnected;
    SOCKET listenSocket;
    std::thread *acceptConnectionsThread;
    std::thread* *receiveDataThreads; //I am using pointers instead of vectors because I want it to be fixed
    ClientObj* *clients;
    std::map<ClientObj*, unsigned int> clientIndexMap;
};

Since I don't know what code to post because I don't even know where the error is coming from, then tell me if you need a specific part of it posted. If I comment out the private copy constructor and assignment operator then it works, but I don't want this to be copyable and especially not through default constructor. Doubt it, but does it have something to do with it being a DLL?

Anyway that's it, thanks for your time

Update

So I added a = delete to the constructor as suggested, and also made it public:

class DLL_PUBLIC Server
{
public:
    Server(unsigned int);
    Server(const Server &par_other) = delete;
    ~Server();

    Server& operator=(const Server &par_other) = delete;

    (...)
};

I am getting a bit of a different error now, but also in the type_traits file:

Error   2   error C2280: '(namespaces..)::Server::Server(const (namespaces..)::Server &)' : attempting to reference a deleted function  (path..)\type_traits    1545    1   Server

A bit of code it is complaining about in that file:

// TEMPLATE FUNCTION _Decay_copy
template<class _Ty> inline
    typename decay<_Ty>::type _Decay_copy(_Ty&& _Arg)
    {   // forward _Arg as value of decayed type
    return (_STD forward<_Ty>(_Arg));
    }
_STD_END

Update 2

So this is the output window from VS as requested:

1>(path...)\type_traits(1545): error C2280: '(namespaces..)::Server::Server(const (namespaces..)::Server &)' : attempting to reference a deleted function
1>          (path..)\Server.h(19) : see declaration of '(namespaces..)::Server::Server'
1>          (path..)\thread(47) : see reference to function template instantiation '(namespaces..)::Server std::_Decay_copy<(namespaces..)::Server&>(_Ty)' being compiled
1>          with
1>          [
1>              _Ty=(namespaces..)::Server &
1>          ]
1>          Server.cpp(94) : see reference to function template instantiation 'std::thread::thread<void(__cdecl &)(const (namespaces..)::Server &),(namespaces..)::Server&>(_Fn,(namespaces..)::Server &)' being compiled
1>          with
1>          [
1>              _Fn=void (__cdecl &)(const (namespaces..)::Server &)
1>          ]

The line 19 in the Server.h it's mentioning is the copy constructor declaration. Line 94 in Server.cpp is thread creation:

pvtImpl->acceptConnectionsThread = new std::thread(acceptConnections, *this);

The acceptConnections function takes the server by constant reference so it shouldn't copy, here's the declaration:

friend void acceptConnections(const Server&);

Upvotes: 0

Views: 229

Answers (1)

arayq2
arayq2

Reputation: 2554

Your problem is most likely in the thread constructor:

pvtImpl->acceptConnectionsThread = new std::thread(acceptConnections, *this);

Try this instead:

pvtImpl->acceptConnectionsThread = new std::thread(acceptConnections, std::ref(*this));

because without the std::ref() wrapper, a copy of your server instance will be passed into the thread constructor, which in turn will pass that copy by reference to your acceptConnections() method. Or at least try to, but it never got that far, as the compiler failed the initial copy.

Upvotes: 4

Related Questions