I have a small program like below:
class boovector{
private: int size;
char *arr;
public:
boovector(){size=1;arr=new char[size];cout<<" boovector default constructor called"<<endl;}
boovector(boovector &b)
{
cout<<"boovector copyconstructor called"<<endl;
size = b.size;
arr = new char[size];
strncpy(arr,b.arr,size);
}
boovector(boovector &&b)
{
cout<<"boovector move assignment operator called"<<endl;
size =b.size;
arr = b.arr;
b.arr = nullptr;
}
~boovector()
{
delete []arr;
}
};
boovector createboovector()
{
boovector v;
return v;
}
void foo(boovector v)
{
}
int main(int argc, char *argv[])
{
boovector vet = createboovector();
foo(vet);
foo(createboovector());
return 0;
}
Output
boovector default constructor called
boovector copyconstructor called
boovector default constructor called
I was hoping to see "boovector move assignment operator called" in the output.
If I comment move constructor "boovector(boovector &&b)", i get compiler error
invalid initialization of non-const reference of type 'boovector&' from an
rvalue of type 'boovector'
I want to understand the logic behind the move constructor not being called.
In my case on MSVC 2017 Community Edition the produced output is:
boovector default constructor called
boovector move assignment operator called
boovector copyconstructor called
boovector default constructor called
boovector move assignment operator called
So it works as expected.
Related
I want to know why control does not go to AB() if I pass in abc(AB) into main() as control goes for initialization of i as 10 when abc(10) is passed
class abc
{
int i;
std::function<void(void)>func = nullptr;
public:
abc(){}
abc(std::function<void(void)>&fb):func(fb){}
abc(int i):i(i){}
};
void AB()
{
cout<< "fun_AB";
}
int main()
{
abc(AB);
abc(10);
}
abc(AB);
This is a declaration of a variable of type abc named AB, equivalent to abc AB;. So the no-arg constructor is called. You could use this syntax if you don't want to name the variable:
abc{AB};
This "works" since it can't be parsed as a declaration, while your version can.
But that's not enough, you need to change your constructor to accept a const&:
abc(std::function<void(void)> const& fb) : func(fb)
{
func(); // if you want AB to be called
}
(Non-const reference won't bind to a temporary.)
Your constructor is called with AB which is a function:
abc(std::function<void(void)>&fb) : func(fb) {}
This initializes func to point to AB, but nothing more. Perhaps you wanted to call it:
abc(std::function<void(void)>&fb) : func(fb) { func(); }
I don't understand why a class that has a deleted copy constructor (or contains a member, like ifstream, that has a deleted copy constructor and there it, too, has a deleted copy constructor) can't be used with make_shared()? This code shows what I'm talking about
class X {
private:
X(const X&) = delete;
int x;
public:
X(int an_int) : x{an_int} {};
X() : x{10} {}
};
int main(int argc, char** argv)
{
// fails because X has no copy constructor
shared_ptr<X> ptr { make_shared<X>( X{8} ) };
shared_ptr<X> ptr2 { new X{10} };// works fine
return 0;
}
You may be missing the fact that make_shared will forward its arguments to the constructor of X. In this case you are passing X{8} as the constructor argument, so make_shared is forced to attempt copy or move construction.
In this particular example, deleting the copy constructor has implicitly deleted the move constructor, preventing construction from the temporary X{8}.
What you probably want to write is this:
shared_ptr<X> ptr { make_shared<X>(8) };
Suppose you want to avoid narrowing when calling a function
void foo(char c) { /* ... */ }
foo(4); // get a compilation error here
You can define your target function, and a forwarding template overload that will attempt a non-narrowing conversion to the target type (DEMO):
void foo(char) {}
template <typename T>
void foo(T&& t) { foo(char{std::forward<T>(t)}); }
foo('a');
// foo(4); // ill-formed
foo({4});
// foo(0); // ill-formed
foo({0});
// foo(u'a'); // ill-formed
foo({u'a'});
int i = 2;
// foo(i); // ill-formed
// foo({i}); // ill-formed
This has the nice advantage that clients can force the conversion themselves by passing a braced-init-list. Since the braced-init-list impedes template deduction, only the target function can be selected by overload resolution. So even though e.g. foo(4) matches the template overload and is ill-formed - since int cannot in general be converted to char without narrowing - foo({4}) is well-formed since 4 can be converted to char without narrowing.
You can use a class template on T that has
1) a template constructor on a different type X that tries to instantiate the class when the parameter is not T
2) a constructor with T as param that takes care of the case where you are instantiating the class with the exact type
#include <iostream>
// g++-4.9 -Werror=narrowing -std=c++11 main2.cc
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55783
template <typename T>
struct no_narrowing
{
using type = T;
// this template constructor lets you try to
// instantiate a no_narrowing using a different
// type. if Narrowing would take place
// value{ val } takes care of it
template <typename X>
no_narrowing(X val) : value{val} {}
// if type is exactly T we use this
no_narrowing(type val) : value{val} {}
operator type() const { return value;}
type value;
};
template <typename T>
using nn = no_narrowing<T>;
void print(nn<char> v)
{
std::cout << v << std::endl;
}
int main(int argc, char *argv[])
{
int i = 2;
print('d');
print(i); // this will not compile
return 0;
}
I really like the idea of properties in C#, and as a little side project, I've been tinkering with the idea of implementing them in C++. I ran into this example https://stackoverflow.com/a/5924594/245869 which seems fairly nice, but I couldn't help but think that lambdas and non-static data member initialization may make it possible to use some very nice syntax with this idea. Here's my implementation:
#include <iostream>
#include <functional>
using namespace std;
template< typename T >
class property {
public:
property(function<const T&(void)> getter, function<void(const T&)> setter)
: getter_(getter),
setter_(setter)
{};
operator const T&() {
return getter_();
};
property<T>& operator=(const T& value) {
setter_(value);
}
private:
function<const T&(void)> getter_;
function<void(const T&)> setter_;
};
class Foobar {
public:
property<int> num {
[&]() { return num_; },
[&](const int& value) { num_ = value; }
};
private:
int num_;
};
int main() {
// This version works fine...
int myNum;
property<int> num = property<int>(
[&]() { return myNum; },
[&](const int& value) { myNum = value; }
);
num = 5;
cout << num << endl; // Outputs 5
cout << myNum << endl; // Outputs 5 again.
// This is what I would like to see work, if the property
// member of Foobar would compile...
// Foobar foo;
// foo.num = 5;
// cout << foo.num << endl;
return 0;
}
I can use my property class normally [see the example in main()], but MinGW with g++4.7 doesn't particularly care for my attempt at using the property as a data member:
\property.cpp: In lambda function:
\property.cpp:40:7: error: invalid use of non-static data member 'Foobar::num_'
So it seems the concept of my property implementation works, but it might be in vain because I can't access other data members from my lambda functions. I'm not sure how the standard defines what I'm trying to do here, am I completely out of luck, or am I just not doing something right here?
Your property is a different object (instance of property<int>) from the containing object (instance of Foobar). As such, its member functions get passed a different this, not the one you'd need to access num_ -- so you can't do it that way. If the lambdas were defined in a non-static member function of Foobar, they would have captured that function's this argument and would have had access to the enclosing object's members (explicitly, as this->num_). But the lambdas are defined in the class, where the non-static data members don't actually exist. If the lambdas did have access to num_, which num_, of which instance of Foobar, would have been that?
The easiest solution that I see is for the property to store a pointer to the enclosing object. That way, it can freely access its non-static members. The downside is that the declaration is slightly more complex (you'd have to do property<int, Foobar> num) and you'd need to initialize the property by passing the this pointer. So you won't be able to do it in the class, it would have to be in the constructor's initialization list, hence negating the advantage of C++11's data member initialization.
At that point, this would be available to the lambdas to capture anyway (by value, not by reference!) so your code would actually work with minimal changes, if you moved the initialization of the property to Foobar's constructor(s):
Foobar::Foobar():
num {
[this]() { return this->num_; },
[this](const int& value) { this->num_ = value; }
}
{
}
Does anyone know whether this, as passed to whatever constructor happens to be invoked, is available for non-static member initialization in the class definition? I suspect it isn't, but if it were, the same construction would work inside the class definition.
I have a Visual Studio 2013 C++11 project where I'm trying to define an iterator. I want that iterator to dereference to an object, but internally it actually iterates over some internal data the object requires for construction.
class my_obj
{
public:
my_obj(some_internal_initialization_value_ v);
std::wstring friendly_name() const;
// ...
};
class my_iterator
: public boost::iterator_facade<
my_iterator,
my_obj,
boost::forward_traversal_tag>
{
// ...
private:
my_obj& dereference() const
{
// warning C4172: returning address of local variable or temporary
return my_obj(some_internal_initialization_value_);
}
};
int main( int argc, char* argv[])
{
my_container c;
for (auto o = c.begin(); o != c.end(); ++o)
printf( "%s\n", o->friendly_name().c_str() );
}
These internal values are unimportant implementation details to the user and I'd prefer not to expose them. How can I write the iterator that does this correctly? The alternative is that I would have to do something like this:
my_container c;
for (auto i = c.begin(); i != c.end(); ++i)
{
my_obj o(*i);
printf( "%s\n", o.friendly_name().c_str() );
}
From the boost page on iterator_facade, the template arguments are: derived iterator, value_type, category, reference type, difference_type. Ergo, merely tell it that references are not references
class my_iterator
: public boost::iterator_facade<
my_iterator,
my_obj,
boost::forward_traversal_tag,
my_obj> //dereference returns "my_obj" not "my_obj&"
See it working here: http://coliru.stacked-crooked.com/a/4b09ddc37068368b