Для единственного объекта, счетного в Java, это был бы Collections.singleton ("строка");
В c# это будет более эффективным, чем новый Список:
public class SingleEnumerator<T> : IEnumerable<T>
{
private readonly T m_Value;
public SingleEnumerator(T value)
{
m_Value = value;
}
public IEnumerator<T> GetEnumerator()
{
yield return m_Value;
}
IEnumerator IEnumerable.GetEnumerator()
{
yield return m_Value;
}
}
, но там более простой способ использовать платформу?
Если вы хотите вернуться по значению и не хотите возиться с возвращаемыми указателями и новыми / удаляемыми, вы можете просто сделать вот так:
template <typename T>
boost::optional<T> Test<T>::FindItem(T item)
{
if(found)
//return original value
else
return boost::none;
}
и использовать это так:
Test<int> var;
boost::optional<int> V = var.FindItem(5)
if (V)
{
// found
int val = *V;
}
else
{
// not found
}
Большинство типов конструируются по умолчанию, у вас есть шаблон признаков класс, который может быть специализированным (по умолчанию возвращается инициализированный объект по умолчанию).
template <class T>
struct Make {
static T Default()
{
return T();
}
};
class not_default_constructable {
public:
explicit not_default_constructable(int i) {}
};
// specialize for not_default_constructable
template <>
struct Make <not_default_constructable> {
static not_default_constructable Default()
{
return not_default_constructable(42);
}
};
У вас есть функция, которая может возвращать действительный объект, но также указывает на то, что действительного объекта не существует. В сочетании с ситуацией, когда допустимы все возможные значения объекта, это проблема проектирования с вашей функцией поиска. (Даже если вы настроили функцию таким образом, чтобы она, например, возвращала пустую строку, если она ее не находила, как это будет отличаться от успешного поиска пустой строки?)
Со временем появилось несколько способов выхода из ситуации. эта дилемма была обнаружена. Таким образом, вы можете вернуть указатель / итератор вместо фактического значения. Тогда итератор указателя / конца NULL
будет указывать «не найден». Или вы можете взять значение по неконстантной ссылке, присвоить ему результат и указать успех / неудачу возвращенным логическим значением. Или возьмите одно из других решений, размещенных здесь. Но все потребует, чтобы вы изменили интерфейс функции, потому что в нем есть ошибка дизайна.
В любом случае, прежде чем вы вскочите и сделаете это, вы должны спросить себя, почему вы пишете свой собственный контейнер / алгоритм вместо использования один из стандартной библиотеки.
Здесь Страуструп приводит пару аргументов для исключения NULL
в C ++:
0
, поэтому фактического усиления нет [и многое другое для ввода] Предложение, опять же с той страницы это:
0
или (для C ++ 0xw независимо) nullptr
. Во-вторых, если вы хотите вернуть недействительный указатель как сигнал об ошибке , вам нужно объявить функцию, возвращающую указатель на тип, а не сам тип.
В-третьих, большинство стандартных библиотечных функций find () возвращают итераторы, а не элементы напрямую. Это дает вам возможность реализовать случай «ничего не найдено» по-другому.
0
или (для C ++ 0x независимо) nullptr
. Во-вторых, если вы хотите вернуть неверный указатель в качестве сигнала об ошибке, вы необходимо объявить функцию как возвращающую указатель на тип, а не сам тип.
В-третьих, большинство стандартных библиотечных функций find () возвращают итераторы, а не элементы напрямую. Это дает вам возможность реализовать случай «ничего не найдено» по-другому.
0
или (для C ++ 0x независимо) nullptr
. Во-вторых, если вы хотите вернуть неверный указатель в качестве сигнала об ошибке, вы необходимо объявить функцию, возвращающую указатель на тип, а не сам тип.
В-третьих, большинство стандартных библиотечных функций find () возвращают итераторы, а не элементы напрямую. Это дает вам возможность реализовать случай «ничего не найдено» по-другому.
Возможно, я слишком упрощаюсь, но я предпочитаю просто возвращать логическое значение
:
template <typename T>
bool Test<T>::FindItem(T item)
{
if (!found)
return false;
item = <found item>;
return true;
}
Return T ()
. Если T
имеет тип sometype *
, он будет инициализирован нулевым указателем. Если T
имеет тип sometype
, он вернет объект, созданный с помощью конструктора по умолчанию, которого должно хватить ( std :: string
будет пустым, целые типы например int
s будет 0 и т. д.).
Вы можете вызвать исключение, если оно не найдено.
Поскольку вы не знаете, какой тип ищется и возвращается, вы не можете назначить какое-либо конкретное значение этого типа как код ошибки. По сути, вы пытаетесь втиснуть весь домен типа плюс значение ошибки в домен типа.
Предложения по использованию итераторов или других оболочек помогают решить проблему, расширяя домен возвращаемого типа для охвата значения ошибок, но если вы хотите придерживаться фактических типов, с которыми имеете дело, исключения - лучший выбор. Вот для чего они нужны.
На мой взгляд, вы пытаетесь немного усложнить себя, пытаясь вернуть значение NULL ...
Вместо этого сделайте что-то подобное:
class SomeError
{};
template <typename T>
T Test<T>::FindItem(T item)
{
if(found)
//return original value, no problem here
else
throw(SomeError);
}
Throwing пустой класс ничего не стоит ...