Implementing move constructor and assignment with unique_ptr<>

I am running on Windows 10 in Visual Studio 2015, using this library for BTSerialPortBinding: https://github.com/Agamnentzar/bluetooth-serial-port

I have the current constructor in my Device.cpp file
1
2
3
4
5
    Device::Device(const char *devName)
    {
        device = devName;
        bt.reset(BTSerialPortBinding::Create(devName, 1));
    }

My Device.h contains a class Device with:
1
2
3
4
    Device(const char *devName="");
    ~Device();
    const char *device;
    std::unique_ptr<BTSerialPortBinding> bt;

I am trying to right a move constructor and move assignment as unique_ptr is not copyable so my class becomes non-copyable and the ~Device() ends up deleting it.

Hence when I try to use:
1
2
3
    Device dev; // declared in Process.h
    
    dev = Device("93:11:22"); // initialised in Process.cpp 

I get the following error:
 
    Device &Device::operator =(const Device &)': attempting to reference a deleted function 

I've tried the following with no luck in Device.h:
1
2
3
4
5
6
7
8
9
10
    //move assignment operator
	Device &operator=(Device &&o)
	{
		if (this != &o)
		{
			bt = std::move(o.bt);
		}
		return *this;
	}
	Device(Device &&o) : bt(std::move(o.bt)) {};

I get these errors when I try this:
1
2
3
4
5
6
7
8
    1>bluetoothserialport.lib(BTSerialPortBinding.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MDd_DynamicDebug' doesn't match value 'MTd_StaticDebug' in ArduinoDevice.obj
    1>bluetoothserialport.lib(BluetoothHelpers.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MDd_DynamicDebug' doesn't match value 'MTd_StaticDebug' in ArduinoDevice.obj
    1>msvcprtd.lib(MSVCP140D.dll) : error LNK2005: "public: __thiscall std::_Lockit::_Lockit(int)" (??0_Lockit@std@@QAE@H@Z) already defined in libcpmtd.lib(xlock.obj)
    1>msvcprtd.lib(MSVCP140D.dll) : error LNK2005: "public: __thiscall std::_Lockit::~_Lockit(void)" (??1_Lockit@std@@QAE@XZ) already defined in libcpmtd.lib(xlock.obj)
    1>msvcprtd.lib(MSVCP140D.dll) : error LNK2005: "void __cdecl std::_Debug_message(wchar_t const *,wchar_t const *,unsigned int)" (?_Debug_message@std@@YAXPB_W0I@Z) already defined in libcpmtd.lib(stdthrow.obj)
    1>msvcprtd.lib(MSVCP140D.dll) : error LNK2005: "void __cdecl std::_Xbad_alloc(void)" (?_Xbad_alloc@std@@YAXXZ) already defined in libcpmtd.lib(xthrow.obj)
    1>msvcprtd.lib(MSVCP140D.dll) : error LNK2005: "void __cdecl std::_Xlength_error(char const *)" (?_Xlength_error@std@@YAXPBD@Z) already defined in libcpmtd.lib(xthrow.obj)
    1>msvcprtd.lib(MSVCP140D.dll) : error LNK2005: "void __cdecl std::_Xout_of_range(char const *)" (?_Xout_of_range@std@@YAXPBD@Z) already defined in libcpmtd.lib(xthrow.obj)
Last edited on
> My Device.h contains a class Device with:
1
2
3
4
> Device(const char *devName="");
> ~Device();
> const char *device;
> std::unique_ptr<BTSerialPortBinding> bt;


Use std::string instead of the raw owing-pointer, and then adhere to the rule of zero.
The implementation would do the right thing.
http://en.cppreference.com/w/cpp/language/rule_of_three

1
2
3
4
5
6
7
8
9
10
11
struct device
{
    explicit device( const std::string& n ) : name(n) {}
    explicit device( std::string&& n ) : name( std::move(n) ) {}
    
    // do not explicitly declare destructor, move constructor or move assignment

    private:
        std::string name ;
        std::unique_ptr<BTSerialPortBinding> bt ;
};

http://coliru.stacked-crooked.com/a/00137b4e1b04303c
http://rextester.com/UOB42080


1>bluetoothserialport.lib(BTSerialPortBinding.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MDd_DynamicDebug' doesn't match value 'MTd_StaticDebug' in ArduinoDevice.obj

1>bluetoothserialport.lib(BluetoothHelpers.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MDd_DynamicDebug' doesn't match value 'MTd_StaticDebug' in ArduinoDevice.obj


Link with either the static library or the DLL consistently; don't try to mix and match on a per-object-file basis.
Last edited on
I get this error when i try to use the bt instance:

1
2
3
Exception thrown: read access violation.

std::_Unique_ptr_base<bluetooth_data,std::default_delete<bluetooth_data> >::_Myptr(...) returned nullptr.


I tried with this code:

http://rextester.com/XMSQ45489
Last edited on
> Exception thrown: read access violation.
> std::_Unique_ptr_base<bluetooth_data,std::default_delete<bluetooth_data> >::_Myptr(...) returned nullptr.


Before accessing an object through a pointer, make sure that it is not a null pointer.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <string>
#include <memory>
#include <iostream>

struct BTSerialPortBinding { 
    
    void connect() { std::cout << "BTSerialPortBinding::connect - stub\n" ; }
    
    /* ... */ 
};

struct Adevice {
    
	explicit Adevice(const std::string& n) : name(n) {}
	explicit Adevice(std::string&& n) : name(std::move(n)) {}

	// do not explicitly declare destructor, move constructor or move assignment
	std::string name;
    
        // http://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique
	std::unique_ptr<BTSerialPortBinding> bt = std::make_unique<BTSerialPortBinding>() ;
};

struct Process {
    
	// explicit Process() {}
    
        void connect() { std::cout << "Process::connect - stub\n" ; if( a && a->bt ) a->bt->connect() ; }
                    
	std::unique_ptr<Adevice> a ; 
};

struct BluetoothException { /* ... */ };

int main() {
    
	std::cout << std::boolalpha
		<< "move_constructible? " << std::is_move_constructible<Adevice>::value << '\n'
		<< "nothrow_move_constructible? " << std::is_nothrow_move_constructible<Adevice>::value << '\n'
		<< "move_assignable? " << std::is_move_assignable<Adevice>::value << '\n'
		<< "nothrow_move_assignable? " << std::is_nothrow_move_assignable<Adevice>::value << '\n';
    
	// Process* aProcess = new Process();
        Process aProcess ;
	aProcess.a = std::make_unique<Adevice>("93:11:22");
    
	try {
        
                std::cout << "\n-------------\n\n" ;
		aProcess.a->bt->connect();

                std::cout << "\n-------------\n\n" ;
                aProcess.connect() ;
	}
    
	catch (const BluetoothException& ) {
        
		std::cout << "fail" << std::endl;
	}
    
	// while (1);
}

http://rextester.com/IXWGQT17261
Topic archived. No new replies allowed.