как вернуть ссылку
От: Аноним  
Дата: 23.10.09 09:58
Оценка: :)))
Подскажите пожалуйста как можно вернуть не существующую ссылку и проверку на существования ссылки.

конечная цель
есть функция возвращающая ссылку на объект, которая проходит список объектов (nextDocument)
на последнем документа следующего объекта нет и надо как то сообщить об этом вызывающей функции

вариант возращать указатель и в случаи если объект не существует вернуть NULL я понимаю но хотелось бы сделать на ссылках
Re: как вернуть ссылку
От: _wf Россия  
Дата: 23.10.09 10:04
Оценка:
exception
Re: как вернуть ссылку
От: Bell Россия  
Дата: 23.10.09 10:09
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Подскажите пожалуйста как можно вернуть не существующую ссылку и проверку на существования ссылки.


А>конечная цель

А>есть функция возвращающая ссылку на объект, которая проходит список объектов (nextDocument)
А>на последнем документа следующего объекта нет и надо как то сообщить об этом вызывающей функции

А>вариант возращать указатель и в случаи если объект не существует вернуть NULL я понимаю но хотелось бы сделать на ссылках


Понятия "нулевая ссылка" в С++ не существует. Соответственно вернуть ее нельзя, проверить — тоже. В твоем случае можно бросить исключение, если требуемый объект не найден.
Любите книгу — источник знаний (с) М.Горький
Re[2]: как вернуть ссылку
От: byleas  
Дата: 23.10.09 10:30
Оценка: -1
Здравствуйте, Bell, Вы писали:

B>Понятия "нулевая ссылка" в С++ не существует. Соответственно вернуть ее нельзя, проверить — тоже.

Нельзя, но если очень хочется...
class document;
document& nextDocument() { document* doc = available ? new document(...) : 0;  return *doc; }

void f()
{
  do {
    document& doc = nextDocument();
    if( &doc == 0 ) break;
  } while(...);
}
Re[3]: как вернуть ссылку
От: Bell Россия  
Дата: 23.10.09 10:36
Оценка: 1 (1) +1
Здравствуйте, byleas, Вы писали:

Не нужно морочить людям голову, и сбивать с правильного пути. Разыменовывание нулевого указателя — неопределенное поведение. И не важно, что приведенный инвалидный код сегодня кое-где прохрамает.
Любите книгу — источник знаний (с) М.Горький
Re: как вернуть ссылку
От: GamerOne Россия  
Дата: 23.10.09 13:09
Оценка: +2
Можно попробовать применить идиому Null Object. При инициализации массива/списка в начало запихивать этот нулевой объект. Если при поиске ничего не найдено, то возвращать ссылку на этот нуль-объект.
Типа так:
#include <boost/shared_ptr.hpp>
#include <string>
#include <vector>
#include <iostream>

struct BaseDocument
{
    virtual ~BaseDocument(){}

    virtual std::string GetName()const = 0;
    virtual std::string GetText()const = 0;
    virtual bool        IsEmpty()const = 0;    
};

struct EmptyDocument: public BaseDocument
{
    virtual ~EmptyDocument(){}

    virtual std::string GetName()const { return ""; }
    virtual std::string GetText()const { return ""; }
    virtual bool        IsEmpty()const { return true; }
};

struct MyDocument: public BaseDocument
{
    virtual ~MyDocument(){}

    virtual std::string GetName()const { return "My Name"; }
    virtual std::string GetText()const { return "The quick brown fox jumps ..."; }
    virtual bool        IsEmpty()const { return false; }
};

typedef boost::shared_ptr<BaseDocument> DocumentPtr;
typedef std::vector<DocumentPtr> DocumentList;

BaseDocument const& Find(DocumentList const& dl)
{
    // эмулируем поиск 
    if(dl.size() > 1)
        return *dl[1]; // типа нашли что-то        
    else
        return *dl[0]; // как будто не нашли и возвращ. нулевой документ по нулевому индексу
}

int main(int argc, char* argv[])
{
    // инициализируем список
    DocumentList dl;
    dl.push_back(DocumentPtr(new EmptyDocument()));

    // список содержит только пустой документ, он и найдется 
    BaseDocument const& doc1 = Find(dl);
    std::cout << "Name=" << doc1.GetName() << " Text=" << doc1.GetText() 
        << " Is empty? " << (doc1.IsEmpty()? "yes": "no") << std::endl;
    
    // добавим что-нубдь в список, чтобы типа "нашелся" нормальный докум.
    dl.push_back(DocumentPtr(new MyDocument()));
    BaseDocument const& doc2 = Find(dl);
    std::cout << "Name=" << doc2.GetName() << " Text=" << doc2.GetText() 
        << " Is empty? " << (doc2.IsEmpty()? "yes": "no") << std::endl;
    return 0;
}
Re: как вернуть ссылку
От: g_i  
Дата: 23.10.09 13:49
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Подскажите пожалуйста как можно вернуть не существующую ссылку и проверку на существования ссылки.


А>конечная цель

А>есть функция возвращающая ссылку на объект, которая проходит список объектов (nextDocument)
А>на последнем документа следующего объекта нет и надо как то сообщить об этом вызывающей функции

А>вариант возращать указатель и в случаи если объект не существует вернуть NULL я понимаю но хотелось бы сделать на ссылках


Возвращай итератор или смартпоинтер, если лирический пятничный велосипедостроительный настрой — можешь сделать самопальный, вида:

template <class T> Reference
{
public:
  Reference<T>(): Obj(0) {}
  explicit Reference<T>(T* obj): Obj(obj()) {}
  Reference<T>& operator =(const Reference<T>& other) {Obj = obj;}
  operator bool() const { return !!Obj; }
  T* operator-> () { return Obj; }
  T& operator*  () { return *Obj; }
private:
  T* Obj;
};

Reference<Document> doc;
while (doc = documents->NextDocument())
{
  doc->DoWhateverYouWant();
}

Либо
template <class T> Iterator
{
public:
  virtual bool Ok() const = 0;
  virtual void Next() = 0;
  virtual T& Get() = 0;
  virtual const T& Get() const = 0;
  virtual ~Iterator<T>() {}
};

for (std::auto_ptr< Iterator<Document> > iter = Documents->GetIterator(); iter->Ok(); iter->Next())
{
  Document& doc = iter->Get();
  doc.DoWhateverYouWant();
}
Re: как вернуть ссылку
От: denisko http://sdeniskos.blogspot.com/
Дата: 23.10.09 13:51
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>Подскажите пожалуйста как можно вернуть не существующую ссылку и проверку на существования ссылки.


А>конечная цель

А>есть функция возвращающая ссылку на объект, которая проходит список объектов (nextDocument)
А>на последнем документа следующего объекта нет и надо как то сообщить об этом вызывающей функции

А>вариант возращать указатель и в случаи если объект не существует вернуть NULL я понимаю но хотелось бы сделать на ссылках


сделай статический объект Type::invalid() и возвращай ссылку на него.
<Подпись удалена модератором>
Re[4]: как вернуть ссылку
От: byleas  
Дата: 23.10.09 16:17
Оценка:
Здравствуйте, Bell, Вы писали:

B>Не нужно морочить людям голову, и сбивать с правильного пути. Разыменовывание нулевого указателя — неопределенное поведение. И не важно, что приведенный инвалидный код сегодня кое-где прохрамает.

Дык нету там разыменования. А так — согласен, не стоит этим пользоваться.
Re: как вернуть ссылку
От: Юрий Жмеренецкий ICQ 380412032
Дата: 23.10.09 19:59
Оценка: 1 (1)
Здравствуйте, Аноним, Вы писали:

А>Подскажите пожалуйста как можно вернуть не существующую ссылку и проверку на существования ссылки.


А>конечная цель

А>есть функция возвращающая ссылку на объект, которая проходит список объектов (nextDocument)
А>на последнем документа следующего объекта нет и надо как то сообщить об этом вызывающей функции

А>вариант возращать указатель и в случаи если объект не существует вернуть NULL я понимаю но хотелось бы сделать на ссылках


while( boost::optional<const Document&> v = a.nextDocument() )    
{
  //...
}
Re[5]: как вернуть ссылку
От: Bell Россия  
Дата: 26.10.09 11:24
Оценка: +1
Здравствуйте, byleas, Вы писали:

B>Дык нету там разыменования.


А как тогда называется вот это?
document& nextDocument() { document* doc = available ? new document(...) : 0;  return *doc; }
Любите книгу — источник знаний (с) М.Горький
Re[6]: как вернуть ссылку
От: byleas  
Дата: 27.10.09 10:24
Оценка:
Здравствуйте, Bell, Вы писали:

B>А как тогда называется вот это?

Так ведь на самом деле ложки не существует.

Это разыменование, с т.з. С++. Но т.к. во всех известных компиляторах ссылки реализованы через указатели, то конструкция "type& t = *pt" на самом деле ничего не делает. Вот я и говорю — разыменования указателя (как обращения к памяти по нему) там нет, в отличие от "type t = *pt".

Да, это UB, и к тому же грязный, с т.з. понимания кода, хак, но он рабочий (в том смысле, что программа не упадёт).
Re[7]: как вернуть ссылку
От: quodum  
Дата: 27.10.09 11:31
Оценка: 6 (1)
Здравствуйте, byleas, Вы писали:

B>Да, это UB, и к тому же грязный, с т.з. понимания кода, хак, но он рабочий (в том смысле, что программа не упадёт).


На CINT проверяли?

Чтобы сэкономить вам время, могу сразу сказать: упадёт.
Re[7]: как вернуть ссылку
От: Кодт Россия  
Дата: 27.10.09 12:23
Оценка: 11 (3)
Здравствуйте, byleas, Вы писали:

B>Да, это UB, и к тому же грязный, с т.з. понимания кода, хак, но он рабочий (в том смысле, что программа не упадёт).


На всякий случай напоминаю: смещение базы для ссылок и указателей работает по-разному.
Точнее, по одинаковому, но у указателей отдельно обрабатывается случай нуля. У ссылок же — компилятор считает, что проверки излишни, ибо ССЗБ.
struct A { ..... };
struct B { ..... };
struct C : A, B { ..... };
struct C2 : B { virtual ...... }; // некоторые компиляторы (MSVC) сдвигают даже первую базу, если нужно ДОБАВИТЬ vfptr

С* pc = 0; // pc==0
B* pb = pc; // pb==0
C* pcb = static_cast<C*>(pb); // pcb==0

C& rc = *pc; // &rc==0
B& rb = *pc; // &rb==нечто положительное, sizeof(A)+выравнивание
C& rcb = static_cast<C&>(*pb); // &rcb==нечто отрицательное, то есть, самый конец сегмента
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
Re[2]: как вернуть ссылку
От: alzt  
Дата: 27.10.09 12:56
Оценка:
Здравствуйте, Bell, Вы писали:

А>>вариант возращать указатель и в случаи если объект не существует вернуть NULL я понимаю но хотелось бы сделать на ссылках


B>Понятия "нулевая ссылка" в С++ не существует. Соответственно вернуть ее нельзя, проверить — тоже. В твоем случае можно бросить исключение, если требуемый объект не найден.


В этом их и прелесть.
Re[8]: как вернуть ссылку
От: barmafon  
Дата: 28.10.09 09:41
Оценка:
Здравствуйте, Кодт, Вы писали:

К>На всякий случай напоминаю: смещение базы для ссылок и указателей работает по-разному.

К>Точнее, по одинаковому, но у указателей отдельно обрабатывается случай нуля. У ссылок же — компилятор считает, что проверки излишни, ибо ССЗБ.

MSVC для ссылок тоже делает проверку: &rc==0, &rb==0, &rcb==0.
Re[9]: как вернуть ссылку
От: Кодт Россия  
Дата: 28.10.09 11:41
Оценка:
Здравствуйте, barmafon, Вы писали:

B>MSVC для ссылок тоже делает проверку: &rc==0, &rb==0, &rcb==0.


Щас надо вспомнить, где-то мне удавалось создать условия, когда он эту проверку не делал...
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
Re[10]: как вернуть ссылку
От: gear nuke  
Дата: 28.10.09 15:54
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Щас надо вспомнить, где-то мне удавалось создать условия, когда он эту проверку не делал...


__assume(&rc == 0);
Но, мне кажется, что VC проверяет только this в конструкторах.
.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re: как вернуть ссылку
От: труженик села  
Дата: 29.10.09 11:30
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Подскажите пожалуйста как можно вернуть не существующую ссылку и проверку на существования ссылки.


А>конечная цель

А>есть функция возвращающая ссылку на объект, которая проходит список объектов (nextDocument)
А>на последнем документа следующего объекта нет и надо как то сообщить об этом вызывающей функции

А>вариант возращать указатель и в случаи если объект не существует вернуть NULL я понимаю но хотелось бы сделать на ссылках


Используешь указатели — возвращай 0, используешь ссылки — кидай exception. Смотри как сделан dynamic_cast.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.