EDIT: I've found out that my question contains a paradox. I used extended initializer list in my code, which was introduced in C++11, but I wanted to use only C++98 tools. Sorry, I noticed my compiler's warning message too late. Of course, move-semantics would have solved my problem in C++11. My question doesn't matter anymore.
I decided to create an own owner_ptr class. The concept is that an owner_ptr object has ownership over a dynamically allocated object (or objects). More than 1 owner_ptr mustn't own the same object. Here is my implementation:
#include <cstddef>
template <typename T>
class owner_ptr
{
    T* ptr;
    bool array;
public:
    owner_ptr() : ptr(NULL) {} /* LINE 10 */
    owner_ptr(T* ptr, bool isArray = false) : ptr(ptr), array(isArray) {} /* LINE 11 */
    owner_ptr(owner_ptr<T>& orig) : ptr(orig.ptr), array(orig.array) /* LINE 12 */
    {
        orig.ptr = NULL;
    }
    ~owner_ptr()
    {
        if (ptr != NULL)
        {
            if (!array)
            {
                delete ptr;
            }
            else
            {
                delete[] ptr;
            }
        }
    }
    owner_ptr& operator=(owner_ptr<T>& rvalue)
    {
        if (this != &rvalue)
        {
            this->~owner_ptr();
            ptr = rvalue.ptr;
            array = rvalue.array;
            rvalue.ptr = NULL;
        }
        return *this;
    }
    void reset()
    {
        this->~owner_ptr();
        ptr = NULL;
    }
    void addPtr(T* newPtr, bool isArray = false)
    {
        this->~owner_ptr();
        ptr = newPtr;
        array = isArray;
    }
    T& operator*() { return *ptr; }
    const T& operator*() const { return *ptr; }
    T* get() { return ptr; }
    const T* get() const { return ptr; }
    T* operator->() { return ptr; }
    const T* operator->() const { return ptr; }
    T& operator[](int i) { return ptr[i]; }
    const T& operator[](int i) const { return ptr[i]; }
};
I specified that it's the user's responsibility to create legal owner_ptr objects like:
owner_ptr<int> op1(new int);
owner_ptr<int> op2(new int[3], true);
owner_ptr<int> op3(op1);
owner_ptr<int> op4;
op4 = op3;
It works well with one-dimensional arrays. However, when I try to allocate a two-dimensional array, this code doesn't compile:
int main()
{
    owner_ptr< owner_ptr<int> > test(new owner_ptr<int>[2]{ owner_ptr<int>(new int[5], true), owner_ptr<int>(new int[8], true) }, true); /* LINE 72 */
    return 0;
}
I got the following messages:
\main.cpp|72|error: no matching function for call to 'owner_ptr<int>::owner_ptr(owner_ptr<int>)'|
\main.cpp|72|note: candidates are:|
\main.cpp|12|note: owner_ptr<T>::owner_ptr(owner_ptr<T>&) [with T = int]|
\main.cpp|12|note:   no known conversion for argument 1 from 'owner_ptr<int>' to 'owner_ptr<int>&'|
\main.cpp|11|note: owner_ptr<T>::owner_ptr(T*, bool) [with T = int]|
\main.cpp|11|note:   no known conversion for argument 1 from 'owner_ptr<int>' to 'int*'|
\main.cpp|10|note: owner_ptr<T>::owner_ptr() [with T = int]|
\main.cpp|10|note:   candidate expects 0 arguments, 1 provided|
\main.cpp|72|error: no matching function for call to 'owner_ptr<int>::owner_ptr(owner_ptr<int>)'|
\main.cpp|72|note: candidates are:|
\main.cpp|12|note: owner_ptr<T>::owner_ptr(owner_ptr<T>&) [with T = int]|
\main.cpp|12|note:   no known conversion for argument 1 from 'owner_ptr<int>' to 'owner_ptr<int>&'|
\main.cpp|11|note: owner_ptr<T>::owner_ptr(T*, bool) [with T = int]|
\main.cpp|11|note:   no known conversion for argument 1 from 'owner_ptr<int>' to 'int*'|
\main.cpp|10|note: owner_ptr<T>::owner_ptr() [with T = int]|
\main.cpp|10|note:   candidate expects 0 arguments, 1 provided|
This is so weird. I have the following questions:
- Why is the compiler looking for a owner_ptr<int>::owner_ptr(owner_ptr<int>)function? Such a copy-constructor would make no sense.
- Why isn't it possible to convert from 'owner_ptr<int>'to'owner_ptr<int>&'?
- How can I fix it? Is it possible to allocate a multi-dimensional (using the owner_ptrtemplate) with only one command?
I know that this works:
owner_ptr< owner_ptr<int> > test(new owner_ptr<int>[2], true);
test[0].addPtr(new int[5], true);
test[1].addPtr(new int[8], true);
However, I'm curious, is it possible to do it with one command.
NOTE: I'm doing this for learning purposes. This is not a production code. So please, don't recommend me to use the C++11 smart pointers.
 
     
    