Тернарный оператор на контенте auto_ptr не работает - PullRequest
3 голосов
/ 07 октября 2009

Я инициализирую auto_ptr в NULL, и позже в игре мне нужно знать, имеет ли он NULL или нет, чтобы вернуть его или новую копию.

Я пробовал это

auto_ptr<RequestContext> ret = (mReqContext.get() != 0) ? mReqContext : new RequestContext();

И еще несколько подобных вещей, но g ++ пытается вызвать несуществующий оператор auto_ptrs? (троичный оператор) вместо использования RequestContext * для троичного сравнения.

Даже если я разыграю его, это не сработает.

Любой намек?

Отредактировано равное для неравных

Ответы [ 6 ]

20 голосов
/ 07 октября 2009

Полагаю, ситуация аналогична следующей:

#include <iostream>
#include <memory>

int main()
{
    std::auto_ptr<int> a(new int(10));
    std::auto_ptr<int> b = a.get() ? a : new int(10);
}

А вот очень поучительное сообщение об ошибке Comeau:

"ComeauTest.c", line 7: error: operand types are incompatible ("std::auto_ptr<int>"
          and "int *")
      std::auto_ptr<int> b = a.get() ? a : new int(10);
                                         ^

Тернарному оператору требуются совместимые типы для обоих результатов, вы не можете заставить его возвращать пользовательский объект в одном случае и пустой указатель в другом. NB! std::auto_ptr принимает указатель в явном конструкторе, что означает, что троичный оператор не может неявно преобразовать второй аргумент в std::auto_ptr

И возможное решение:

std::auto_ptr<int> b = a.get() ? a : std::auto_ptr<int>(new int(10));
2 голосов
/ 07 октября 2009

mReqContext имеет тип auto_ptr<RequestContext>, верно? Тогда проблема может быть в несовместимых типах по обе стороны от :, потому что new RequestContext() дает RequestContext *, но оба должны иметь общий тип, чтобы троичный оператор мог использоваться.

Возможные решения: либо используйте

auto_ptr<RequestContext>(new RequestContext)

на правой стороне : или используйте

mReqContext.get()

на левой стороне :.

В обоих случаях: остерегайтесь проблем с владением указателем с auto_ptr! (Необработанный) указатель в auto_ptr может принадлежать только одному объекту auto_ptr, поэтому оба моих «простых» решения могут быть не тем, что вам нужно (первое очищает mReqContext, если оно не -нуля, второй нет, но может привести к удалению дубликата mReqContext).

1 голос
/ 07 октября 2009

1001 * попробовать *

auto_ptr<RequestContext> ret;
ret.reset(new stuff here);
0 голосов
/ 07 октября 2009

Убедитесь, что вы не назначаете указатель на auto_ptr, это не будет работать. Однако все эти фрагменты компилируются просто отлично:

#include <memory>
#include <string>

using namespace std;
int main(int argc, char * argv[] )
{
    auto_ptr<int> pX;
    pX.reset(pX.get() ? new int(1) : new int(2));
    pX = auto_ptr<int>(pX.get() ? new int(1) : new int(2));
    pX = auto_ptr<int>((pX.get()==NULL) ? new int(1) : new int(2));

    return 0;
}
0 голосов
/ 07 октября 2009

Вы пытались положить все это в фигурные скобки?

auto_ptr<RequestContext> ret =
    (mReqContext.get() == 0) ? (mReqContext) : (new RequestContext());
0 голосов
/ 07 октября 2009

Вы пробовали разбить это на две строки?

RequestContext *p = (mReqContext.get() == 0) ? mReqContext : new RequestContext();
auto_ptr<RequestContext> ret = p;
...