使用模板

时间:2016-12-29 06:37:01

标签: c++ templates reference move

我正在尝试使用我理解的模板在C ++中实现一个智能指针(基本上是唯一的指针)。

这就是我编码的内容

using namespace std;

template<typename T>
class smartPointer
{
    private:
        T *mPtr;
    public:
        smartPointer(T* init=nullptr):mPtr(init)
        {
            cout<<"Inside ctr"<<endl;
        }


        //silence the default ctr
        smartPointer() = delete;

        //disable copy ctr and copy assignment
        smartPointer  (const smartPointer& other) = delete;
        smartPointer& operator=(const smartPointer& other) = delete;

        //implement move ctr and move assignment
        smartPointer  (smartPointer&& other)
        {
            cout<<"Inside move ctr "<<endl;
            mPtr = other.mPtr;
            other.mPtr = nullptr;
        }
        smartPointer& operator=(smartPointer&& other)
        {

            cout<<"Inside move = before "<<endl;
            if(&other != this)
            {
                mPtr = other.mPtr;
                other.mPtr = nullptr;

                cout<<"Inside move = after "<<endl;
            }
        return *this;
        }

        //deference
        T& operator*()
        {
            return *mPtr;
        }

        //arrow  access operator
        T* operator->()
        {   
            return mPtr;
        }

        ~smartPointer()
        {   
            cout<<"Inside ~dtr"<<endl;
            if(mPtr != nullptr)
            delete mPtr;
        }

};



int main()
{

     smartPointer<int> sptr(new int);

     // Even smartPointer<int> sptr(new int[20]); too works

     *sptr = 10;
     cout<<"Value pointed by the pointer  is "<<*sptr<<endl;     

    smartPointer<int> sptr2(new int);

//  sptr2 = sptr; // complains as expected
    sptr2 = move(sptr); // works well

    /*
    How to 

    smartPointer<int[]>  sptr(new int[20]); 
    */

    return 0;
}

如何使这个智能指针适用于smartPointer?

我给出的构建命令是 g ++ -std = c ++ 11 -smartPointer.cpp -o smartPointer

1 个答案:

答案 0 :(得分:1)

您可以将operator[]添加到基本模板,并使用SFINAE确保它仅在类型为数组类型时进行编译。您也可以这样做以确保operaotr*operaotr->仅针对非阵列版本进行编译。然后,标签分派可用于调用正确的delete表达式。

template<typename T>
class smartPointer
{
    private:
        T *mPtr;

        del_member(std::true_type) { delete[] mPtr; }
        del_member(std::false_type) { delete mPtr; }

    public:
        // Removed you code for brevity.

        //deference
        auto operator*() -> std::enable_if_t<!std::is_array<T>::value, T&>
        {
            return *mPtr;
        }

        //arrow  access operator
        auto operator->() -> std::enable_if_t<!std::is_array<T>::value, T*>
        {   
            return mPtr;
        }

        auto operator[](std::size_t idx) -> std::enable_if_t<std::is_array<T>::value, T&>
        {   
            return mPtr[idx];
        }

        ~smartPointer()
        {   
            del_member(std::is_array<T>{});
        }
};

以上是完全合法的,并且可以存在于同一模板中。请记住,模板的成员仅在使用时才会实例化。因此,除非您的类的用户尝试使用一个底层指针不应该支持的运算符,否则它们不会出错。

如果您的编译器还不支持c ++ 14类型特征,则可以将上述尾随返回类型转换为以下格式:

typename std::enable_if<CONDITION, TYPE>::type

对于您的c,我建议您不要硬编码T*。而是在您的班级中添加以下类型别名,并相应地更改c。#。

using ptr_type = std::conditional_t<std::is_array<T>::value, std::decayt_t<T>, std::add_pointer_t<T>>;

smartPointer(ptr_type init)