jeudi 2 avril 2015

Unexpected invocation of deleted move constructor by gcc

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?


Aucun commentaire:

Enregistrer un commentaire