#include <iostream>
#include <cstdlib>
using namespace std;
class c
{
public:
c(){ cout << "Default ctor" << endl; }
c(const c& o) { cout << "Copy ctor" << endl; }
c(c&& o){ cout << "move copy ctor" << endl; } // Line 11
//c(c&& o) = delete; // Line 12
~c() { cout << "Destructor" << endl; }
};
int main()
{
c o = c(); // Line 18
c p = std::move(c());
return 0;
}
This piece of code produces the below output.
Default ctor
Default ctor
move copy ctor
Destructor
Destructor
Destructor
However, if I deactivate line#11 and activate line#12 then it gives below compile time error.
prog.cc: In function 'int main()':
prog.cc:18:13: error: use of deleted function 'c::c(c&&)'
18 | c o = c();
| ^
prog.cc:12:9: note: declared here
12 | c(c&& o)=delete;
| ^
which implies that, line#18 invokes the move copy constructor provided by compiler. How to get my user defined move constructor in line#11 invoked without using std::move?
Or std::move is the only way to get user defined move constructors invoked?
Related
I'm having troubles understanding fully the assignment operator for unique_ptr. I understand that we can only move them, due to the fact that copy constructor and assignment operators are deleted, but what if
a unique_ptr which contains already an allocation is overwritten by a move operation? Is the content previously stored in the smart pointer free'd?
#include <iostream>
#include <memory>
class A{
public:
A() = default;
virtual void act() const {
std::cout << "act from A" << std::endl;
}
virtual ~A() {
std::cout << "destroyed A" << std::endl;
}
};
class B : public A {
public:
B() : A{} {}
void act() const override {
std::cout << "act from B" << std::endl;
}
~B() override {
std::cout << "destroyed from B " << std::endl;
}
};
int main() {
auto pP{std::make_unique<A>()};
pP->act();
==================== ! =======================
pP = std::make_unique<B>(); // || std::move(std::make_unique<B>())
==================== ! =======================
pP->act();
return 0;
}
When I do
pP = std::make_unique<B>();
does it mean that what was allocated in the first lines for pP (new A()) is destructed automatically?
Or should I opt for:
pP.reset();
pP = std::make_unique<B>();
Yes, see section 20.9.1, paragraph 4 of the C++11 draft standard
Additionally, u can, upon request, transfer ownership to another unique pointer u2. Upon completion of
such a transfer, the following postconditions hold:
u2.p is equal to the pre-transfer u.p,
u.p is equal to nullptr, and
if the pre-transfer u.d maintained state, such state has been transferred to u2.d.
As in the case of a reset, u2 must properly dispose of its pre-transfer owned object via the pre-transfer
associated deleter before the ownership transfer is considered complete
In other words, it's cleaning up after itself upon assignment like you'd expect.
Yes, replacing the content of a smart pointer will release the previously-held resource. You do not need to call reset() explicitly (nor would anyone expect you to).
Just for the sake of this particular example. It seems polymorphism in your example didn't allow you to draw clear conclusions from output:
act from A
destroyed A
act from B
destroyed from B
destroyed A
So let's simplify your example and make it straight to the point:
#include <iostream>
#include <memory>
struct A {
explicit A(int id): id_(id)
{}
~A()
{
std::cout << "destroyed " << id_ << std::endl;
}
int id_;
};
int main() {
std::unique_ptr<A> pP{std::make_unique<A>(1)};
pP = std::make_unique<A>(2);
}
which outputs:
destroyed 1
destroyed 2
Online
I hope this leaves no room for misinterpretation.
In the following code, as none of the arguments is const, i can't understand why the second overload is called in the 3 following cases.
#include <iostream>
#include <algorithm>
using namespace std;
void ToLower( std::string& ioValue )
{
std::transform( ioValue.begin(), ioValue.end(), ioValue.begin(), ::tolower );
}
std::string ToLower( const std::string& ioValue )
{
std::string aValue = ioValue;
ToLower(aValue);
return aValue;
}
int main()
{
string test = "test";
cout<<"Hello World" << endl;
// case 1
cout << ToLower("test") << endl;
// case 2
cout << ToLower(static_cast<string>(test)) << endl;
// case 3
cout << ToLower(string(test)) << endl;
}
In all 3 cases you are creating a temporary std::string, this is an unnamed object, an R-value. R-values aren't allowed to bind to non-const l-value references (T&) and so only the overload taking const std::string& ioValue is valid.
The reasoning is the return type is std::string for the second function but void for the first. std::cout << (void) << std::endl is not a valid set of operations. std::cout << (std::string) << std::endl is. If you return a std::string& from the first function you'd probably see #2 & #3 probably use your first function call.
I have the following code snipet:
// code snipet one:
#include <memory>
#include <iostream>
#include <queue>
struct A {
uint32_t val0 = 0xff;
~A() {
std::cout << "item gets freed" << std::endl;
}
};
typedef std::shared_ptr<A> A_PTR;
int main()
{
std::queue<A_PTR> Q;
Q.push(std::make_shared<A>());
auto && temp_PTR = Q.front();
std::cout << "first use count = " << temp_PTR.use_count() << std::endl;
Q.pop();
std::cout << "second use count = " << temp_PTR.use_count() <<std::endl;
return 0;
}
After running it, I got the result as following:
first use count = 1
item gets freed
second use count = 0
Q1: is anybody can explain what the type of temp_PTR after the third line of main function is called?
if I change that line as
A_PTR && temp_PTR = Q.front();
compiler complains that
main.cpp: In function 'int main()':
main.cpp:26:32: error: cannot bind '__gnu_cxx::__alloc_traits > >::value_type {aka std::shared_ptr}' lvalue to 'A_PTR&& {aka std::shared_ptr&&}'
A_PTR && temp_PTR = Q.front();
Q2: I remember that the return value of a function should be a r-value, but it seems here the compiler tell me: " hey, the return value of Queue.front() is a l-value", why is here?
For Q2, I just check the C++ docs, that the return value of Queue.front() is refernece, that means it return a l-value
reference& front();
const_reference& front() const;
For Q3, it works for A_PTR temp_PTR = std::move(Q.front());, it is what I want.
I am struggling with compile time errors, and try as I might, I dont see in what way am I doing it wrong or different from handler function signature as set out in documentation/examples. (I am using Boost 1.41 on Linux)
Please help me understand the error! (included below as snippet)
My application has objects whose methods are handlers for async_* functions. Below is the code snippet. The error is reported in the line labelled as "line 58", where I use boost::bind
class RPC {
public:
char recv_buffer[56];
void data_recv (void) {
socket.async_read_some (
boost::asio::buffer(recv_buffer),
boost::bind ( &RPC::on_data_recv, this, _1, _2 )
); // **<<==== this is line 58, that shows up in error listing**
global_stream_lock.lock();
std::cout << "[" << boost::this_thread::get_id()
<< "] data recvd" << std::endl;
global_stream_lock.unlock();
} // RPC::data_recv
void on_data_recv (boost::system::error_code& ec, std::size_t bytesRx) {
global_stream_lock.lock();
std::cout << "[" << boost::this_thread::get_id()
<< "] bytes rcvd: " << std::endl;
global_stream_lock.unlock();
data_recv(); // call function that waits for more data
} // RPC::on_data_recv
}; // RPC class def
There is a huge error output, but the relevant lines seem to be:
../src/besw.cpp:58: instantiated from here
/usr/include/boost/bind/bind.hpp:385: error: no match for call to ‘(boost::_m fi::mf2<void, RPC, boost::system::error_code&, long unsigned int>) (RPC*&, boost::asio::error::basic_errors&, int&)’
/usr/include/boost/bind/mem_fn_template.hpp:272: note: candidates are: R boost::_mfi::mf2<R, T, A1, A2>::operator()(T*, A1, A2) const [with R = void, T = RPC, A1 = boost::system::error_code&, A2 = long unsigned int]
/usr/include/boost/bind/mem_fn_template.hpp:291: note: R boost::_mfi::mf2<R, T, A1, A2>::operator()(T&, A1, A2) const [with R = void, T = RPC, A1 = boost::system::error_code&, A2 = long unsigned int]
make: *** [src/besw.o] Error 1
When I remove the place holders (_1 and _2) and have a handler without arguments, then it compiles and executes without errors. Here's that modified code snippet.
void data_recv (void) {
socket.async_read_some (
boost::asio::buffer(recv_buffer),
boost::bind ( &RPC::on_data_recv, this )
);
global_stream_lock.lock();
std::cout << "[" << boost::this_thread::get_id()
<< "] data recvd" << std::endl;
global_stream_lock.unlock();
} // RPC::data_recv
void on_data_recv (void) {
...
}
The error code cannot be taken by reference. Make it by-value or by const&:
void on_data_recv(boost::system::error_code/* ec */, size_t /*bytes_transferred*/) {
Also, consider using the Asio specific placeholders:
socket.async_read_some(boost::asio::buffer(recv_buffer),
boost::bind(&RPC::on_data_recv, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
Also use proper lock guards. We're in C++! It's easy to make things exception-safe, so why not?
Live On Coliru
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <boost/thread.hpp>
static boost::mutex global_stream_lock;
class RPC {
char recv_buffer[56];
public:
void data_recv() {
socket.async_read_some(boost::asio::buffer(recv_buffer),
boost::bind(&RPC::on_data_recv, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
boost::lock_guard<boost::mutex> lk(global_stream_lock);
std::cout << "[" << boost::this_thread::get_id() << "] data recvd" << std::endl;
global_stream_lock.unlock();
}
void on_data_recv(boost::system::error_code/* ec */, size_t /*bytes_transferred*/) {
{
boost::lock_guard<boost::mutex> lk(global_stream_lock);
std::cout << "[" << boost::this_thread::get_id() << "] bytes rcvd: " << std::endl;
}
data_recv(); // call function that waits for more data
}
boost::asio::io_service service;
boost::asio::ip::tcp::socket socket{service};
}; // RPC class def
int main() {}
Using C++11, I'd like to call a static member function template without qualifying it with the scope of its enclosing class:
struct Test {
template<typename T>
static bool Function(T x)
{ /* ... */ }
};
int x;
Test::Function(x); // I don't want to write this
Function(x); // I want to be able to write this instead
I can define another function with the same signature at global scope and forward the arguments, but I'd prefer a solution that doesn't force me to write another function. I'd also like to avoid using a macro.
This question is related:
(using alias for static member functions?)
but doesn't seem to cover the case of function templates.
Sure, you can alias the templated function if you want to do a little work with the using keyword first:
template<typename T>
using testfn = bool (*)(T);
and then create a pointer to the function with:
testfn<int> fnPointer = Test::Function;
and finally call it:
std::cout << boolalpha << fnPointer(x) << std::endl;
Live Demo
If you only ever want to bind to the case where T is int, you can do this:
using testfn = bool (*)(int);
//...
testfn fnPointer = Test::Function;
std::cout << boolalpha << fnPointer(x) << std::endl;
Live Demo 2
Edit: If you want a constexpr function pointer like in the accepted answer of the question you linked, that's a pretty simple extension:
constexpr auto yourFunction = &Test::Function<int>;
//...
std::cout << boolalpha << yourFunction(x) << std::endl;
Live Demo 3
I learned this playing with the #andyg answer (probably above mine), but it worked for me and it doesn't require putting a different alias for every template.
It requires c++14 or later though.
Step 1 - magical template alias:
template <typename T> constexpr auto funky1 = &Test::Function<T>;
Step 2 - lambda means you don't need to pass the template argument:
auto funky = [](auto in) { return funky1<decltype(in)>(in); };
full example
Also, inline full example:
#include <iostream>
struct Test {
template <typename T> static bool Function(T x) { return true; }
};
// Magical template alias
template <typename T> constexpr auto funky1 = &Test::Function<T>;
// lambda means it'll infer the template parameters when calling
auto funky = [](auto in) { return funky1<decltype(in)>(in); };
int main() {
int x = 0;
// Just use the `funky1` version, but you have to specify the template parameters
std::cout << "string: " << funky1<std::string>("I'm a string") << std::endl
<< "int: " << funky1<int>(42) << std::endl
<< "bool: " << funky1<bool>(true) << std::endl;
// Use the `funky` version, where template parameters are inferred
std::cout << "string: " << funky("I'm a string") << std::endl
<< "int: " << funky(42) << std::endl
<< "bool: " << funky(true) << std::endl;
return 0;
}