Подскажите пожалуйста как можно вернуть не существующую ссылку и проверку на существования ссылки.
конечная цель
есть функция возвращающая ссылку на объект, которая проходит список объектов (nextDocument)
на последнем документа следующего объекта нет и надо как то сообщить об этом вызывающей функции
вариант возращать указатель и в случаи если объект не существует вернуть NULL я понимаю но хотелось бы сделать на ссылках
Здравствуйте, Аноним, Вы писали:
А>Подскажите пожалуйста как можно вернуть не существующую ссылку и проверку на существования ссылки.
А>конечная цель А>есть функция возвращающая ссылку на объект, которая проходит список объектов (nextDocument) А>на последнем документа следующего объекта нет и надо как то сообщить об этом вызывающей функции
А>вариант возращать указатель и в случаи если объект не существует вернуть NULL я понимаю но хотелось бы сделать на ссылках
Понятия "нулевая ссылка" в С++ не существует. Соответственно вернуть ее нельзя, проверить — тоже. В твоем случае можно бросить исключение, если требуемый объект не найден.
Здравствуйте, 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(...);
}
Не нужно морочить людям голову, и сбивать с правильного пути. Разыменовывание нулевого указателя — неопределенное поведение. И не важно, что приведенный инвалидный код сегодня кое-где прохрамает.
Можно попробовать применить идиому 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;
}
Здравствуйте, Аноним, Вы писали:
А>Подскажите пожалуйста как можно вернуть не существующую ссылку и проверку на существования ссылки.
А>конечная цель А>есть функция возвращающая ссылку на объект, которая проходит список объектов (nextDocument) А>на последнем документа следующего объекта нет и надо как то сообщить об этом вызывающей функции
А>вариант возращать указатель и в случаи если объект не существует вернуть NULL я понимаю но хотелось бы сделать на ссылках
Возвращай итератор или смартпоинтер, если лирический пятничный велосипедостроительный настрой — можешь сделать самопальный, вида:
Здравствуйте, Аноним, Вы писали:
А>Подскажите пожалуйста как можно вернуть не существующую ссылку и проверку на существования ссылки.
А>конечная цель А>есть функция возвращающая ссылку на объект, которая проходит список объектов (nextDocument) А>на последнем документа следующего объекта нет и надо как то сообщить об этом вызывающей функции
А>вариант возращать указатель и в случаи если объект не существует вернуть NULL я понимаю но хотелось бы сделать на ссылках
сделай статический объект Type::invalid() и возвращай ссылку на него.
Здравствуйте, Bell, Вы писали:
B>Не нужно морочить людям голову, и сбивать с правильного пути. Разыменовывание нулевого указателя — неопределенное поведение. И не важно, что приведенный инвалидный код сегодня кое-где прохрамает.
Дык нету там разыменования. А так — согласен, не стоит этим пользоваться.
Здравствуйте, Аноним, Вы писали:
А>Подскажите пожалуйста как можно вернуть не существующую ссылку и проверку на существования ссылки.
А>конечная цель А>есть функция возвращающая ссылку на объект, которая проходит список объектов (nextDocument) А>на последнем документа следующего объекта нет и надо как то сообщить об этом вызывающей функции
А>вариант возращать указатель и в случаи если объект не существует вернуть NULL я понимаю но хотелось бы сделать на ссылках
while( boost::optional<const Document&> v = a.nextDocument() )
{
//...
}
Здравствуйте, Bell, Вы писали:
B>А как тогда называется вот это?
Так ведь на самом деле ложки не существует.
Это разыменование, с т.з. С++. Но т.к. во всех известных компиляторах ссылки реализованы через указатели, то конструкция "type& t = *pt" на самом деле ничего не делает. Вот я и говорю — разыменования указателя (как обращения к памяти по нему) там нет, в отличие от "type t = *pt".
Да, это UB, и к тому же грязный, с т.з. понимания кода, хак, но он рабочий (в том смысле, что программа не упадёт).
Здравствуйте, 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==нечто отрицательное, то есть, самый конец сегмента
Здравствуйте, Bell, Вы писали:
А>>вариант возращать указатель и в случаи если объект не существует вернуть NULL я понимаю но хотелось бы сделать на ссылках
B>Понятия "нулевая ссылка" в С++ не существует. Соответственно вернуть ее нельзя, проверить — тоже. В твоем случае можно бросить исключение, если требуемый объект не найден.
Здравствуйте, Кодт, Вы писали:
К>На всякий случай напоминаю: смещение базы для ссылок и указателей работает по-разному. К>Точнее, по одинаковому, но у указателей отдельно обрабатывается случай нуля. У ссылок же — компилятор считает, что проверки излишни, ибо ССЗБ.
MSVC для ссылок тоже делает проверку: &rc==0, &rb==0, &rcb==0.
Здравствуйте, Кодт, Вы писали:
К>Щас надо вспомнить, где-то мне удавалось создать условия, когда он эту проверку не делал...
__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
Здравствуйте, Аноним, Вы писали:
А>Подскажите пожалуйста как можно вернуть не существующую ссылку и проверку на существования ссылки.
А>конечная цель А>есть функция возвращающая ссылку на объект, которая проходит список объектов (nextDocument) А>на последнем документа следующего объекта нет и надо как то сообщить об этом вызывающей функции
А>вариант возращать указатель и в случаи если объект не существует вернуть NULL я понимаю но хотелось бы сделать на ссылках
Используешь указатели — возвращай 0, используешь ссылки — кидай exception. Смотри как сделан dynamic_cast.