2

我正在寻找一种可以使用其他类型的赋值来初始化但不能复制的类型。这个想法类似于作用域智能指针,因为我希望这种类型的对象在其生命周期内拥有资源,但我也希望能够使用赋值语法。所以在概要中,这就是我想要的:

T x = new U; // allowed
T y(new U);  // allowed
T z = x;     // not allowed
T x2(x)      // not allowed

这是我到目前为止所尝试的......

#include <boost/noncopyable.hpp>

class U {};

class T : boost::noncopyable {
public:
    T(U *p) : p_(p) {
    }

    ~T() {
        delete p_;
    }

    operator bool() const { return p_ != 0; }

private:
    U *p_;
};

int main() {
    T x = new U; // allowed
    T y(new U);  // allowed
    //T z = x;     // not allowed
    //T x2(x)      // not allowed
}

不幸的是,这会导致错误:

$ g++ test.cc -o test /usr/include/boost/noncopyable.hpp: 在复制构造函数'T::T(const T&)': /usr/include/boost/noncopyable.hpp:27:7: 错误: 'boost::noncopyable_::noncopyable::noncopyable(const boost::noncopyable_::noncopyable&)' 是私有的 test.cc:6:30: 错误:在这个上下文中 test.cc: 在函数'int main()'中: test.cc:20:12:注意:这里首先需要合成方法 'T::T(const T&)'

注意:C++11 的移动功能对我来说是不可选择的,因为它必须能够使用不支持 C++11 的相对较旧版本的 gcc 进行编译。

由于缺乏 C++11 支持,我不确定是否有“好的”解决方案。但我想我会问。

4

1 回答 1

1

如果我对评论的理解是正确的 - 你想要这样的东西:

U* create_T() { return new U; }
if (T t = create_T())
{
  // do something with t
}

这里的问题,已经在评论中提到:这种语法T t = u只是调用复制构造函数。如果 u 是类型T,则它等价于:T t(u)。如果u像在您的示例中一样,是可转换为T( here by T::T(U*)) 的另一种类型,则实际上是这样的:T t(T(u))。所以在这里你有编译器抱怨的复制构造函数。

没有解决方案,因为这不是有效的if语法:

if (T i(create_T())) {}

但是,如果没有好的建议,我不会写所有这些;)

您可以使用以下语法忘记复制构造函数的问题:

if (U* u = create_T()) {
   T t(u);
   ....
} 

顺便说一句,std::auto_ptr和你的类型有同样的问题T。只需将显式添加到您的T(U*)构造函数中,您就会看到与以下内容的相似性auto_ptr

class U {};

class T : boost::noncopyable {
public:
    explicit T(U *p) : p_(p) {
    }

    ~T() {
        delete p_;
    }

private:
    U *p_;
};

int main() {
    T x = new U; // allowed
    T y(new U);  // allowed
    std::auto_ptr<U> a = new U;
    std::auto_ptr<U> b(new U);
}

结果是:

prog.cpp:25: error: conversion from ‘U*’ to non-scalar type ‘T’ requested
prog.cpp:27: error: conversion from ‘U*’ to non-scalar type ‘std::auto_ptr<U>’ requested

在这里我的ideone研究...

于 2012-09-04T19:40:44.943 回答