Create object only if some condition, otherwise return nullptr - c++

I want to create an object only if some conditions are applied, otherwise retun nullptr. This is how I would do it in Delphi (2009+):
function GetGen(n : integer) : Generics.Collections.TList<Integer>;
var
i : integer;
begin
result := nil;
if n > 0 then begin
result := Generics.Collections.TList<Integer>.Create;
for i := 0 to n - 1 do result.Add(i);
end;
end;
procedure TestGenList(n : integer);
var
aInt : integer;
aGen : Generics.Collections.TList<Integer>;
begin
aGen := GetGen(n);
if aGen = nil then begin
WriteLn('No generic created!');
Exit;
end;
WriteLn(Format('Size: %d', [aGen.Count]));
for aInt in aGen do Write(Format('%d ', [aInt]));
aGen.Free; //will clear integers
end;
procedure TestGen
begin
TestGenList(0);
Readln;
TestGenList(5);
Readln;
end.
This is how I could do it in C++ :
unique_ptr<vector<int>> GetUniquePrtVec(int n){
if (n < 1) return(nullptr); //create only if correct input is given
unique_ptr<vector<int>> result (new vector<int>);
for (int i = 0 ; i != n; i++){
result->push_back(i);
}
return(move(result));
}
void TestPtrVec(int n){
unique_ptr<vector<int>> vec = GetUniquePrtVec(n);
if (vec == nullptr){
cout << "No vector created" << endl;
return;
}
cout << endl << vec->size() << endl;
for_each(vec->begin(), vec->end(), [](int n){cout << n << " " << endl;});
vec->clear(); //clear vector
vec.reset(nullptr);
}
void testVec3(){
TestPtrVec(0);
TestPtrVec(5);
}
My question is about the right idiom. Would you guys, experienced C++ programmers (for I am a beginner, just learning the language), do it this way? If not, then how would you do it?
Thanks.

IMHO, the best way for your example, would be to simply return the std::vector by value and simply return an empty one if the input is invalid.
std::vector<int> get_vec(int n){
std::vector<int> ret;
for(unsigned i=0; i < n; ++i)
ret.push_back(i);
return ret; // will be empty for (n < 1)
// and will be moved if (n >= 1)
}
One thing you need to learn: You don't need to explicitly std::move if you return a local variable. Just return by value. If copy elision is possible, it will do that (RVO / NRVO). If it can't for some reason, it'll first try to move it out before copying it. Note however, that a member of a local variable will not be moved automatically, aka
struct object{ std::vector<int> member; };
std::vector<int> foo(){
object o;
// ...
return o.member; // no move, no copy elision, plain old copy
}
Now, your second function can also be improved and reduced:
void try_vec(int n){
auto vec = get_vec(n); // will elide copy or simply move
for(auto& x : vec) // will not loop if vector is empty
std::cout << x << ' '; // why space and newline?
std::cout << "\n"; // don't use std::endl, it also flushes the stream
}
And from your original function:
vec->clear(); //clear vector
vec.reset(nullptr);
Is not needed, that's the whole reason for smart pointers and resource managing containers. They will destroy what they own when they go out of scope.

personally I believe that having a pointer to a vector is a bit necessary it looks as to me as if you could just return an empty vector or even throw an invalid argument error. The whole null return value is a bit of a hack and now you have to manage some memory because of it.
I personally would rather see
std::vector<int> get_vec(int n){
std::vector<int> result;
if(n < 1) return result;
result.reserve(n);
for (int i = 0 ; i != n; i++){
result.push_back(i);
}
return result;
}
or
std::vector<int> get_vec(int n){
if(n < 1) throw std::invalid_argument("n must be greater than 1");
std::vector<int> result;
result.reserve(n);
for (int i = 0 ; i != n; i++){
result.push_back(i);
}
return result;
}
void test(int n){
try{
std::vector<int> vec = get_vec(n);
catch(const std::exception& e)
{
std::cerr << "No vector created: " << e.what() << std::endl;
return;
}
//etc. . .

Seems what you need is something like boost::optional. Here is an example of its usage:
optional<char> get_async_input()
{
if ( !queue.empty() )
return optional<char>(queue.top());
else return optional<char>(); // uninitialized
}
void receive_async_message()
{
optional<char> rcv ;
// The safe boolean conversion from 'rcv' is used here.
while ( (rcv = get_async_input()) && !timeout() )
output(*rcv);
}
For more information refer to boost documentation.

Use exceptions or type erasure, returning NULL is the C way of doing things, not the C++ way.
Also you use the move semantic but you are not returning an r-value, it would not work like that.

Im a little unfamilliar with this syntax, but I think it looks okay to me. Though, why not just use pointers with the usual c+ syntax?
vector<int> GetUniquePrtVec(int n)
{
if (n < 1)
return null;
vector<int>* result = new vector<int>;
for (int i = 0 ; i != n; i++){
result->push_back(i);
}
return (result);
}
Though Ive never used a vector pointer. Generally when I create a vector I pass it to a function by reference, like this:
vector<int> myVec;
bool bSuccess = PopulateVec(n, myVec);
vector<int>* PopulateVec(int inNum, vector<int>& inVec)
{
if (inNum< 1)
return false;
for (int i = 0 ; i != inNum; i++)
{
inVec->push_back(i);
}
// inVec is "returned" by reference
return true
}

Related

Return struct element from vector c++

I'm new to C++ and I'm trying to return a struct from a vector of structs by using 2 search criteria.
The function find_city is returning me everything from the defined range, regardless of whether it exists inside the vector of struct.
Here's my code:
struct cityLoc
{
int hRange;
int vRange;
int cityCode;
string cityName;
};
vector<cityLoc> cl1;
// the vector has already been preloaded with data
// function to return my struct from the vector
cityLoc find_city(int hRange, int vRange)
{
for (size_t i = 0; i < cl1.size(); i++)
{
if ((cl1[i].hRange = hRange) && (cl1[i].vRange = vRange))
{
return cl1[i];
}
}
}
int main()
{
for (int i = 0; i < 8; i++)
{
for (int j = 0; j <= 8; j++)
{
cityLoc this_city;
this_city = find_city(i, j);
cout << this_city.hRange << ", " << this_city.vRange << endl;
}
}
return 0;
}
Also, aside from this question, I was previously looking into std::find_if and didn't understand it. If I have the following code, what is the output? How do I modify it such that it returns a struct?
auto it = find_if(cl1.begin(), cl1.end(), [](cityLoc& cl) { return cl.hRange == 1; } );
You have a bug here:
if ((cl1[i].hRange = hRange) && (cl1[i].vRange = vRange))
Those = are assignments, not comparisons! Please enable compiler warnings and you won't be hurt by such obvious typos in future.
std::find_if will return the iterator to the found struct entry if it is successful, std::vector::end() otherwise. So, you should first validate the returning iterator if it is valid or not.
For example:
auto it = std::find_if( cl1.begin(), cl1.end(),
[](const cityLoc& cl) { return cl.hRange == 1; } );
if ( it == cl1.end() )
{
// ERROR: Not found! Return error code etc.
return -1;
}
// And, if found, process it here...
std::cout << it->hRange << '\n';
std::cout << it->vRange << '\n';
The criteria (predicate) part in std::find_if is a lambda expression.

std::vector initialization in another function

I need to initialize vectors and check whether the initialization has been successful many times, so I decided to create a function for that. The problem is that I haven't been able to find a way to tackle this problem without losing a significant amount of efficiency. This has been my attempt so far:
#include <iostream>
#include <vector>
bool init(std::vector<double>& v, int n, double x) {
try {
v = std::vector<double>(n, x);
}
catch (std::bad_alloc& e) {
std::cerr << "Error: " << e.what() << std::endl;
return false;
}
return true;
}
int main() {
int n = -1;
std::vector<double> v;
if (not init(v, n, 1)) {
std::cerr << "Vector failed to initialize" << std::endl;
}
else {
for (int i = 0; i < n; ++i) {
std::cout << v[i] << std::endl;
}
}
}
Notice that I create a new vector and then call the copy constructor, so the cost is similar to initializing two vectors instead of one. Is there an efficient alternative to this?
Notice that I create a new vector and then call the copy constructor, so the cost is similar to initializing two vectors instead of one.
I do not think so.
You create an empty std::vector<double> v, which is a relatively cheap operation, and then assign it a new value inside init().
However, in init() a temporary std::vector<double>(n, x) is assigned to v, so the move assignment operator, not the copy constructor, will be called and no unnecessary copying is performed.
You cannot initialize something after it has been constructed. However, the simplest "solution" to your "problem" is to construct the vector in place instead of using an "init" function with an "output parameter".
int main() {
int n = -1;
try
{
std::vector<double> v(n, 1);
for (int i = 0; i < n; ++i) {
std::cout << v[i] << std::endl;
}
}
catch(const std::bad_alloc&)
{
std::cerr << "Vector failed to initialize" << std::endl;
}
}
If you really need an "init" function for your vector, then return by value and use it to initialize something at the caller side.
std::vector<double> init(int n, double x) {
return std::vector<double>(n, x);
}
Both versions leave you with less things to think about. For example, you don't have to instantiate and empty vector first, then check the return value of a function (which you can easily neglect to do) and you don't have to document what happens if a non-empty vector gets passed, or read the documentation if you're the user of the function.

How to use boost::optional

I am trying to use boost::optional as below.
#include <iostream>
#include <string>
#include <boost/optional.hpp>
struct myClass
{
int myInt;
void setInt(int input) { myInt = input; }
int getInt(){return myInt; }
};
boost::optional<myClass> func(const std::string &str)
{
boost::optional<myClass> value;
if(str.length() > 5)
{
// If greater than 5 length string. Set value to 10
value.get().setInt(10);
}
else if (str.length() < 5)
{
// Else set it to 0
value.get().setInt(0);
}
else
{
// If it is 5 set the value to 5
value.get().setInt(5);
}
return value;
}
int main()
{
boost::optional<myClass> v1 = func("3124");
boost::optional<myClass> v2 = func("helloWorld");
boost::optional<myClass> v3 = func("hello");
if (v1)
std::cout << "v1 is valid" << std::endl;
else
std::cout << "v1 is not valid" << std::endl;
if (v2)
std::cout << "v2 is valid" << std::endl;
else
std::cout << "v3 is not valid" << std::endl;
if (v3)
std::cout << "v3 is valid" << std::endl;
else
std::cout << "v3 is not valid" << std::endl;
return 0;
}
I get following error
prog.exe:
/usr/local/boost-1.55.0/include/boost/optional/optional.hpp:631:
boost::optional::reference_type boost::optional::get() [with T =
myClass; boost::optional::reference_type = myClass&]: Assertion
`this->is_initialized()' failed.
Presumably, the optional variable is not initialized properly. How to do it the correct way?
EDIT:: Got some very good answers, just couple of more questions 1. Is it a good idea to use make_optional at the end of 'func' function and return it? Also 2. I was thinking of assigning boost::none to emphasize that I have no value to assign and that's why boost::none. But not sure if that is valid?
A default-constructed boost::optional is empty - it does not contain a value, so you can't call get() on it. You have to initialise it with a valid value:
boost::optional<myClass> value = myClass();
Alternatively, you can use an in-place factory to avoid copy initialisation (but the copy will most likely be elided anyway); however, I have no experience with that, so I can't provide an example.
As a side note, you can use -> in place of get(), like this:
value->setInt(10);
But that's just a matter of stylistic preference, both are equally valid.
How to do it the correct way?
boost::optional<myClass> func(const std::string &str)
{
if(str.length() > 5)
return myClass{10};
if(str.length() < 5)
return myClass{0};
return myClass{5};
}
As a side note, this code doesn't need boost::optional, because there is no code branch that returns an empty object (it is semantically equivalent to returning a myClass instance).
To return an empty optional, use this:
boost::optional<myClass> func(const std::string &str)
{
if(str.length() > 5)
return myClass{10};
if(str.length() < 5)
return myClass{0};
return boost::none; // return empty object
}
Idiomatic client code (don't pre-initialize your values):
int main()
{
if (auto v1 = func("3214"))
// use *v1 to access value
std::cout << "v1 is valid" << std::endl;
else
std::cout << "v1 is not valid" << std::endl;
return 0;
}
Two easy approaches:
boost::optional<myClass> func(const std::string &str)
{
boost::optional<myClass> value;
if(str.length() > 5) // If greater than 5 length string. Set value to 10
value = 10;
else if (str.length() < 5) // Else set it to 0
value = 0;
else // If it is 5 set the value to 5
value = 5;
return value;
}
boost::optional<myClass> func(const std::string &str)
{
if(str.length() > 5) // If greater than 5 length string. Set value to 10
return 10;
else if (str.length() < 5) // Else set it to 0
return 0;
else // If it is 5 set the value to 5
return 5;
}
note that returning an optional from a function that never returns an empty optional is a bad idea.
optional behaves like a pointer on read access -- you can only read the value from it if you have already verified there is something there to read. You can check if there is something to read by doing bool something_to_read = opt;.
You can, however, write to it whenever. If there is nothing there, it creates something. If there is something there, it overwrites it.
.get() is a reading, not a writing, operation. (it "reads" the reference) It is only safe to use when the optional is engaged and has data. Confusingly, you can write to the "read access" .get() return value, as it is a non-const reference.
So maybe "read" and "write" are bad words to use. :)
It is sometimes helpful to think of optional as a value-and-pointer mixed together. There is a possibly null pointer to an owned buffer of memory that may, or may not hold a copy of the type.
If the pointer inside the optional is null, then the buffer is uninitialized. If it points at the buffer, then the buffer is initialized.
.get() dereferences that pointer and returns the resulting reference without checking. = checks the pointer, if it is null, it does a copy-construct from the rhs into the buffer and sets the pointer. If not, it just assigns to the buffer.
(The pointer is conceptual: usually implemented as a bool flag).
I find using *optional to be better than optional.get(), as the "you must check before you dereference" is more obvious with the dereference operator.
boost::optional<myClass> func(const std::string &str)
{
boost::optional<myClass> value; //not init is invalid
if(str.length() > 5) // If greater than 5 length string. Set value to 10
value = 10;
else if (str.length() < 5) // Else set it to 0
value = 0;
return value;
}
v1 is valid
v2 is valid
v3 is not valid
according to boost,optional default ctor will create an optional obj as invalid
optional<T> def ; //not initalize with a obj T
assert ( !def ) ;

Vectors of pointers to other vector's elements

EI have function which takes as parameter pointer to vector:
void Function(std::vector<type>* aa)
Now inside this function I want to filter out data from that vector to another vector and I want to change data of original vector by changing values of this temporary one. Damn it's hard to understand something like:
void Function(std::vector<type>* aa)
{
std::vector<type*> temp; //to this vector I filter out data and by changning
//values of this vector I want to autmatically change values of aa vector
}
I have something like that:
void Announce_Event(std::vector<Event>& foo)
{
std::vector<Event> current;
tm current_time = {0,0,0,0,0,0,0,0,0};
time_t thetime;
thetime = time(NULL);
localtime_s(&current_time, &thetime);
for (unsigned i = 0; i < foo.size(); ++i) {
if (foo[i].day == current_time.tm_mday &&
foo[i].month == current_time.tm_mon &&
foo[i].year == current_time.tm_year+1900)
{
current.push_back(foo[i]);
}
}
std::cout << current.size() << std::endl;
current[0].title = "Changed"; //<-- this is suppose to change value.
}
That does not change original value.
I think you may be having trouble communicating your intentions, so this calls for a psychic answer.
void Func(std::vector<type> & aa)
{
std::vector<type*> temp;
// I wish <algorithm> had a 'transform_if'
for(int i=0; i<aa.size(); ++i)
{
if( some_test(aa[i]) )
temp.push_back(&aa[i])
}
// This leaves temp with pointers to some of the elements of aa.
// Only those elements which passed some_test(). Now any modifications
// to the dereferenced pointers in temp will modify those elements
// of aa. However, keep in mind that if elements are added or
// removed from aa, it may invalidate the pointers in temp.
}
Do not use a pointer to a vector, use a reference instead:
void Function(std::vector<type>& aa)
inside the function you can now access the vectors contents as usual.
void Function(std::vector<type>& aa)
{
std::vector<type>& temp = aa;
// if you now append something to temp, it is also appended to aa
aa.push_back(type());
}
I don't know why you want two references to one vector, but hey, you asked :)
EDIT: removed typo, see comments. thanx
As an aside, start formatting your code better. Messy code is difficult to understand and makes it harder for you to figure out what you're trying to do.
This will do what you want:
void Oglos_Wydarzenie(std::vector<Wydarzenie>& zmienna)
{
std::vector<Wydarzenie *> obecne;
tm AktualnyCzas = {0,0,0,0,0,0,0,0,0};
time_t czas;
czas = time(NULL);
localtime_s(&AktualnyCzas,&czas);
for (unsigned i = 0; i < zmienna.size(); ++i) {
if (zmienna[i].dzien == AktualnyCzas.tm_mday &&
zmienna[i].miesiac == AktualnyCzas.tm_mon &&
zmienna[i].rok == AktualnyCzas.tm_year+1900)
{
obecne.push_back(&zmienna[i]);
}
}
std::cout << obecne.size() << std::endl;
obecne[0]->tytul = "Changed"; //<-- this is suppose to change value.
}
You could do this with all pointers and no references at all, but then it looks much more confusing:
void Oglos_Wydarzenie(std::vector<Wydarzenie>* zmienna)
{
std::vector<Wydarzenie *> obecne;
tm AktualnyCzas = {0,0,0,0,0,0,0,0,0};
time_t czas;
czas = time(NULL);
localtime_s(&AktualnyCzas,&czas);
for (unsigned i = 0; i < zmienna->size(); ++i) {
if ((*zmienna)[i].dzien == AktualnyCzas.tm_mday &&
(*zmienna)[i].miesiac == AktualnyCzas.tm_mon &&
(*zmienna)[i].rok == AktualnyCzas.tm_year+1900)
{
obecne.push_back(&((*zmienna)[i]));
}
}
std::cout << obecne.size() << std::endl;
obecne[0]->tytul = "Changed"; //<-- this is suppose to change value.
}

How to access the element of a list/vector that passed by reference in C++

The problem is passing lists/vectors by reference
int main(){
list<int> arr;
//Adding few ints here to arr
func1(&arr);
return 0;
}
void func1(list<int> * arr){
// How Can I print the values here ?
//I tried all the below , but it is erroring out.
cout<<arr[0]; // error
cout<<*arr[0];// error
cout<<(*arr)[0];//error
//How do I modify the value at the index 0 ?
func2(arr);// Since it is already a pointer, I am passing just the address
}
void func2(list<int> *arr){
//How do I print and modify the values here ? I believe it should be the same as above but
// just in case.
}
Is the vectors any different from the lists ? Thanks in advance.
Any links where these things are explained elaborately will be of great help. Thanks again.
You aren't passing the list by reference, but by a pointer. In "C talk" the two are equal, but since there is a reference type in C++, the distinction is clear.
To pass by reference, use & instead of * - and access "normally", i.e.
void func(list<int>& a) {
std::cout << a.size() << "\n";
}
To pass by pointer, you need to derefer the pointer with an asterisk (and do take note of operator presedence), i.e.
void func(list<int>* arr) {
std::cout << (*a).size() << "\n"; // preferably a->size();
}
There is no operator[] in std::list.
//note the return type also!
void func1(list<int> * arr)
{
for (list<int>::iterator i= arr->begin() ; i!= arr->end(); i++ )
{
//treat 'i' as if it's pointer to int - the type of elements of the list!
cout<< *i << endl;
}
}
In your example, return type of func1() is not specified. So I specified it. You may change from void to some other type. Also don't forget to specify return type for func2() and main() too.
If you want to use subscript operator [], then you've to use std::vector<int>, as list<> doesn't overload operator[]. In that case, you can write :
for(std::vector<int>::size_type i = 0 ; i < arr->size() ; i++ )
{
cout << (*arr)[i] << endl;
}
I'm still assuming arr is pointer to vector<int>.
Maybe, you would like to modify your code a little bit, like this:
void func1(vector<int> & arr) // <-- note this change!
{
for(std::vector<int>::size_type i = 0 ; i < arr.size() ; i++ )
{
cout << arr[i] << endl;
}
}