Unexpected invocation of deleted move constructor by gcc - c++11

I'm trying to write a very simple array class with a function that returns a subsection of itself. It is easier to show it than to explain...
template<typename T>
class myArrayType
{
// Constructor; the buffer pointed to by 'data' must be held
// elsewhere and remain valid for the lifetime of the object
myArrayType(int size, T* data) : n(size), p(data)
{
}
// A move constructor and assign operator wouldn't make
//much sense for this type of object:
#ifndef _MSC_VER
myArrayType(myArrayType<T> &&source) = delete;
myArrayType & operator=(myArrayType<T> &&source) && = delete;
#else
#if _MSC_VER >= 2000
myArrayType(myArrayType<T> &&source) = delete;
myArrayType & operator=(myArrayType<T> &&source) && = delete;
#endif
// Earlier versions of Visual C++ do not generate default move members
#endif
// Various whole-array operations, which is the main reason for wanting to do this:
myArrayType & operator+=(const myArrayType &anotherArray) & noexcept
{
for (int i=0; i<n; ++i) p[i] += anotherArray.p[i];
return *this;
}
// etc.
// The interesting bit: create a new myArrayType object which is
// a subsection of this one and shares the same memory buffer
myArrayType operator()(int firstelement, int lastelement) noexcept
{
myArrayType newObject;
newObject.p = &p[firstelement];
newObject.n = lastelement - firstelement + 1;
return newObject;
}
private:
T* p;
int n;
}
What I'd like to do, of course, is to be able to write:
double aBigBlobOfMemory[1000]; // Keep it on the stack
myArrayType<double> myArray(1000, aBigBlobOfMemory);
myArrayType<double> mySmallerArray = myArray(250, 750);
...so that 'mySmallerArray' is a fully-formed myArrayType object which contains a pointer to a subset of myArray's memory.
In Visual Studio 2013 this seems to work (or at least, it compiles), but in gcc it fails in a way that I don't understand. The compiler error on the attempted creation of mySmallerArray is:
use of deleted function myArrayType(myArrayType<T> &&)
...with a caret pointing to the end of the line. In other words, gcc seems to think that in invoking the 'subarray operator' I'm actually trying to invoke a move constructor, but I can't for the life of me see where it would want to use one, or why.
Am I missing something really really obvious, or can anyone shed some light on this?

gcc is doing the right thing.
From operator() you are returning newObject, an instance of myArrayType. This has to be moved into the variable mySmallerArray. That's done with a move constructor, which you don't have.
You need to declare a move constructor.
It does make sense for this class to have a move constructor - it can move the pointer p from the existing instance to the new one.

Related

Why should we initialize data members on declaration (not necessarily on constructor)?

Does anyone could explain me the reason of this coding recommendation ?
Since C++11, please initialize data members on declaration (not
necessary on constructor) :
class Limit
{
public:
Limit() = default;
private:
int32_t quantity = 0;
double price = 0.0;
};
Someone thinks (correctly) that this way the variable is always initialised. Which is a good thing if it is initialised with a meaningful value and bad if the value is not meaningful. For example a person’s year of birth is a number from say 1890 to 2021. Initialising it to 0 isn’t useful and can only prevent the compiler from warning you.
So do this if you have a value that is always a useful initialisation value. I wouldn’t do it for anything that is likely to be overwritten in a constructor or shortly after.
I found this answer from CppCoreGuidelines C-48 :
C.48: Prefer in-class initializers to member initializers in constructors for constant initializers
Reason
Makes it explicit that the same value is expected to be used in all constructors. Avoids repetition. Avoids maintenance problems. It leads to the shortest and most efficient code.
Example, bad
class X { // BAD
int i;
string s;
int j;
public:
X() :i{666}, s{"qqq"} { } // j is uninitialized
X(int ii) :i{ii} {} // s is "" and j is uninitialized
// ...
};
How would a maintainer know whether j was deliberately uninitialized (probably a bad idea anyway) and whether it was intentional to give s the default value "" in one case and qqq in another (almost certainly a bug)? The problem with j (forgetting to initialize a member) often happens when a new member is added to an existing class.
Example
class X2 {
int i {666};
string s {"qqq"};
int j {0};
public:
X2() = default; // all members are initialized to their defaults
X2(int ii) :i{ii} {} // s and j initialized to their defaults
// ...
};
Alternative: We can get part of the benefits from default arguments to constructors, and that is not uncommon in older code. However, that is less explicit, causes more arguments to be passed, and is repetitive when there is more than one constructor:
class X3 { // BAD: inexplicit, argument passing overhead
int i;
string s;
int j;
public:
X3(int ii = 666, const string& ss = "qqq", int jj = 0)
:i{ii}, s{ss}, j{jj} { } // all members are initialized to their defaults
// ...
};
Enforcement
(Simple) Every constructor should initialize every member variable (either explicitly, via a delegating ctor call or via default construction).
(Simple) Default arguments to constructors suggest an in-class initializer might be more appropriate.
There is also the guideline C-45 that explains it.

Why is private move constructor allowed while initalizing via static method?

Simplified code snippet is:
class A {
public:
~A();
static A create();
private:
A() = default;
A(A&&) = default;
NonCopyable n;
};
A A::create() {
A a;
return a;
}
int main(int argc, char* argv[]) {
auto a = A::create();
return 0;
}
Please also see my live example (which shows different compilers' behavior).
In the end, I'm wondering why does auto a = A::create(); compile without errors using newer compilers [gcc >= 7.1] (which part of the C++17 standard is relevant here?), given that:
We have a non-copyable member NonCopyable n;, so default copy constructor would be ill-formed.
It's an NRVO here since A a; return a; so copy elision is not guaranteed by the standard.
Move constructor A(A&&) is marked private.
Optimizations were off -O0 for testing.
My suspicion is that move constructor is being "validated" by the compiler at return a;; since this is a member function of A it passes the validation. Even if the suspicion is correct, I'm not sure if this is standard-compliant.
I believe this is a consequence of P0135: Wording for guaranteed copy elision through simplified value categories, specifically the change to [dcl.init]:
If the initializer expression is a prvalue and the cv-unqualified version of the source type is the same class as the class of the destination, the initializer expression is used to initialize the destination object.
[Example: T x = T(T(T())); calls the T default constructor to initialize x. — end example]
As a result, this behavior is not dependent on copy elision of return values or the availability of move constructors.

How to use std::bind properly with std::unique_ptr

I am trying to std::bind class functions in combination of std::unique_ptr and I have a lot of trouble getting it to work
First I have two classes
class simpleClass{
public:
simpleClass(int x){
this->simpleNumber = x;
}
int simpleNumber;
simpleClass(const simpleClass &toBeClone){
this->simpleNumber = toBeClone.simpleNumber;
}
simpleClass clone(){
simpleClass *cloned = new simpleClass(*this);
return *cloned;
}
};
class className{
public:
className(doube input){
this->someVariable = input;
}
void someFunction(std::vector<double> x, double c, std::unique_ptr<simpleClass> &inputClass, std::vector<double> &output){
std::vector<double> tempOutput;
for(int i = 0; i<x.size(); i++){
tempOutput.push_back(x[i] + c * this->someVariable + inputClass->simpleNumber);
}
output = tempOutput;
}
double someVariable;
className(const className &toBeClone){
this->someVariable = toBeClone.someVariable;
}
className clone(){
className *cloned = new className(*this);
return *cloned;
}
};
They are both some standard class, but I also implement a clone function to duplicate an initialized class. While cloning, I need to ensure that the original class and the cloned class points to different address. So I use std::unique_ptr to ensure this.
The is the main function, which also shows how I "clone"
int main(){
className testSubject(5);
std::vector<std::unique_ptr<className>> lotsOfTestSubject;
simpleClass easyClass(1);
std::vector<std::unique_ptr<simpleClass>> manyEasyClass;
for(int i = 0; i<10; i++){
std::unique_ptr<className> tempClass(new className(testSubject.clone()))
lotsOfTestSubject.push_back(std::move(tempClass));
std::unique_ptr<simpleClass> tempEasyClass(new simpleClass(easyClass.clone()))
manyEasyClass.push_back(std::move(tempEasyClass));
}
std::vector<std::vector<<double>> X; //already loaded with numbers
double C = 2;
std::vector<std::vector<<double>> OUT;
for(int i = 0; i<10; i++){
std::vector<double> tempOUT;
lotsOfTestSubject[i]->someFunction(X[i], C, manyEasyClass[i], tempOUT);
OUT.push_back(tempOUT);
//Here if I want to bind
/*
std::bind(&className::someFunction, lotsOfTestSubject[i], X[i], C, manyEasyClass[i], tempOUT);
*/
}
return 0;
}
The reason why I "clone" is because both simpleClass and className takes a lot of time for construction in my implementation, and I need a lot of them. And Since many of them will be initialized with the same parameters, I figured this is the easiest way to do so.
The code above works, but I am trying to improve the speed of the loop. The following line is where most of the computation takes place.
lotsOfTestSubject[i]->someFunction(X[i], C, manyEasyClass[i], tempOUT);
So I am attempting to use threads to delegate the work , and as far as I know, I need to std::bind first. So I tried
std::bind(&className::someFunction, lotsOfTestSubject[i], X[i], C, manyEasyClass[i], tempOUT);
But the compiler prints error like this
/usr/include/c++/5/tuple|206| recursively required from ‘constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(const _Head&, const _Tail& ...) [with long unsigned int _Idx = 1ul; _Head = std::vector<double>; _Tail = {double, std::unique_ptr<simpleClass, std::default_delete<simpleClass> >, std::unique_ptr<simpleClass, std::default_delete<simpleClass> >, std::vector<double>}]’|
/usr/include/c++/5/tuple|108|error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = className; _Dp = std::default_delete<className>]’|
I have no idea what this means as I just started self teaching c++. Any feedback and guidance is much appreciated.
I am using c++11 and g++ (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609
Update
Thanks #rafix07, tried your solution and it works fine. but then I tried to do
auto theBinded = std::bind(&className::someFunction, &lotsOfTestSubject[i],
X[i], C, std::ref(manyEasyClass[i]), tempOUT);
std::thread testThread(theBinded);
and eventually want to testThread.join()
But the compiler says
error: pointer to member type ‘void (className::)(std::vector<double>, double, std::unique_ptr<simpleClass>&, std::vector<double>&)’ incompatible with object type ‘std::unique_ptr<className>’|
#kmdreko Thanks for you point out! I haven't notice memory leak yet, but I will fix it. Do I just use this?
std::unique_ptr<className> tempClass = new className(testSubject);
EDIT
If you want to call someFunction on instance stored in lotsOfTestSubject you need to pass pointer to className object on which this method will be called, so the line below
std::bind(&className::someFunction, lotsOfTestSubject[i]
should be replaced by:
auto theBinded = std::bind(&className::someFunction, lotsOfTestSubject[i].get(),
^^^
Second change is to use std::ref to pass original instance of unique_ptr of manyEasyClass instead of its copy. std::bind always copies or moved its arguments (see reference), but unique_ptr is non-copyable, that is why compilation failed.
So fixed line looks:
auto theBinded = std::bind(&className::someFunction, lotsOfTestSubject[i].get(),
X[i], C, std::ref(manyEasyClass[i]), std::ref(tempOUT));
tempOUT also must be passed by std::ref because you want to modify this vector by call operator() on functor created by bind.
LIVE DEMO

C++ why overloading (T&) in template with (T*)

in C++, if a method is accepting left reference + pointer only,
it seems it suffices if we only have a template method with T& as its parameter, why we usually overload with test(T* ) as well ?
proof of concept: left reference method can take pointer argument.
#include <iostream>
using namespace std;
template<class T>
void test(T& arg) {
T value = arg;
cout << *value << endl;
}
int main() {
int b = 4;
int* a = &b;
test(a); // compiles and runs without issue.
return 0;
}
Why [do] we usually overload with test(T* ) as well?
I am not sure that we usually do anything of the sort, but if one were to overload for a pointer, it would be because pointers behave differently than object types. Remember, a pointer in fact is not an object but an address to an object.
The reason that test(a) compiles and runs without issue is because it is accepting a reference to a pointer to an object as its parameter. Thus, when the line cout << *value << endl; executes, the pointer is dereferenced back to an object and we see 4 printed to standard out.
As #HolyBlackCat mentioned, we usually want do different things for T& and T*.
As indicated in the example, for test(T&) we usually need to manually do dereference, this would result in the difference in the behavior, so it makes sense to have a overload like this.

Run a function when number of references decrease in shared_ptr

I am developing a cache and I need to know when an object expired.
Is possible run a function when the reference counter of a shared_ptr decrease?
std::shared_ptr< MyClass > p1 = std::make_shared( MyClass() );
std::shared_ptr< MyClass > p2 = p1; // p1.use_count() = 2
p2.reset(); // [ run function ] p1.use_count() = 1
You can't have a function called every time the reference count decreases, but you can have one called when it hits zero. You do this by passing a "custom deleter" to the shared_ptr constructor (you can't use the make_shared utility for this); the deleter is a callable object which is responsible for being passed, and deleting, the shared object.
Example:
#include <iostream>
#include <memory>
using namespace std;
void deleteInt(int* i)
{
std::cout << "Deleting " << *i << std::endl;
delete i;
}
int main() {
std::shared_ptr<int> ptr(new int(3), &deleteInt); // refcount now 1
auto ptr2 = ptr; // refcount now 2
ptr.reset(); // refcount now 1
ptr2.reset(); // refcount now 0, deleter called
return 0;
}
You can specify a deleter functor when creating the shared_ptr. The following article show an example use of a deleter:
http://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr
Not using a vanilla std::shared_ptr, but if you only require customized behaviour when calling reset() (with no arguments), you can easily create a custom adapter:
template <typename T>
struct my_ptr : public std::shared_ptr<T> {
using std::shared_ptr<T>::shared_ptr;
void reset() {
std::shared_ptr<T>::reset(); // Release the managed object.
/* Run custom function */
}
};
And use it like this:
my_ptr<int> p = std::make_shared<int>(5);
std::cout << *p << std::endl; // Works as usual.
p.reset(); // Customized behaviour.
Edit
This answer is meant to suggest a solution to an issue that I didn't think the other answers did address, that is: executing custom behaviour every time when the refcount is decreased by use of reset().
If the issue is simply to make a call upon object release, then use a custom deleter functor as suggested in the answers by #Sneftel and #fjardon.

Resources