0
votes

Consider following class of custom array

template <typename element, unsigned int size>
class array
{
private:
    element (&data)[size];
public:
    array(element (&reference)[size]):data(reference){}
    array():data(new element [size]){} // This is where my problem arises
};

Obviously, in initialization list of constructor evaluates the rvalue expression (the new-expression) to rvalue of pointer instead of reference type. So in MSVC (Microsoft Visual Studio 2012 RC) prompts the error about type conversion from element * to element (&)[size].

However, I think that if I can perhaps convert the rvalue from pointer to reference, it should compile. Is there any chance I can make it there in initialization list of constructor? Or perhaps it just all conflicts with the principle of C++ language? I've investiaged into reinterpret_cast, but the only rule I find relevant is

"An lvalue expression of type T1 can be converted to reference to another type T2. The result is an lvalue or xvalue referring to the same object as the original lvalue, but with a different type." - cppreference.com

which clearly states that the conversion applies to lvalue expression.

OK, I know what you might think now - why do you need such class of custom array and why don't you just composite pointer instead of the problemtic reference? Well...you always need different approaches to choose before knowning the best don't you?

2
Let's imagine you could somehow cast the result of new to fit your use case. How would you ever be able to delete that correctly?Mat
This question has nothing to do with rvalue references, and there's nothing specific to C++11 either that I can see.user743382
@Mat You got the point ;D. Actually, there is one flag in the class, indicating if data is a reference that wraps or not. If it wraps, it doesn't delete. Otherwise it does. It didn't come up with the class I posted here for convenience.Yang
@Yang: That is an anti-pattern. You should redesign so that the class does a task and need not care whether the memory is to be released or not.David Rodríguez - dribeas
@DavidRodríguez-dribeas There is one circumstance this pattern is useful. Supposing invention of dynamic or weak typed language based on C++ and user is not expected to new or delete upon declaring variable of this array type, memory allocation must be managed upon construction. Nevertheless, of course I wouldn't make use of it in serious job :-).Yang

2 Answers

2
votes

What's this about C++11 and rvalue references? To get a lvalue expression to the value pointed to by a pointer, just use the unary * operator. It's been part of the language since the beginning. All you have to do here is make sure you get a pointer to an array, rather than a pointer to the first element of the array.

template <typename element, unsigned int size>
class array
{
private:
    element (&data)[size];
public:
    array() : data(*new element[1][size]) { }
    array(element (&reference)[size]) : data(reference) { }
};

As mentioned by Mat in his comment, the parameterless constructor here is a very bad idea, because the memory will not be freed. Hopefully, having a working code sample will allow you to experiment a bit and come to the same conclusion.

0
votes

You are not at all using R-Value references in this code. There is not a single usage of && r-value symbol.

EDIT:

template <typename element, unsigned int size> 
class array 
{ 
private: 
    element (&data)[size]; 
    static element DefaultArrRef[size];
public: 
    //array(element (&reference)[size]):data(reference){} 
    array():data(DefaultArrRef){}
}; 


template <typename element, unsigned int size> 
element array<element,size>::DefaultArrRef[size];