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 ) ;
Related
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.
I would like the function to return different types depending on different parameter values, but how can I print the variable the void pointer points to
in main()?
#include <iostream>
#include <string>
using namespace std;
void * func(int a)
{
if (a == 1)
{
int param = 5;
return ¶m;
}
else if (a == 2)
{
double param = 5.5;
return ¶m;
}
else if (a == 3)
{
string param = "hello";
return ¶m;
}
else
{
return nullptr;
}
}
int main()
{
void *ptr = func(3);//
cout << ptr;// print the address not the value
getchar();
return 0;
}
param is an automatic variable. You cannot return it and use it outside its scope.
param exists only within func, if you return it, the result is Undefined Behaviour.
To fix it you can either:
allocate param on the heap dynamically. After you do that, you can safely return param address but you have to remember to free it when you don't need it.
Here is correction of your code
#include <iostream>
#include <string>
#include <string.h>
using namespace std;
void * func(int a)
{
if (a == 1)
{
int *param = new int(5);
return param;
}
else if (a == 2)
{
double *param = new double(5.5);
return param;
}
else if (a == 3)
{
char *param = new char[50];
strcpy(param, "test");
return param;
}
return nullptr;
}
int main()
{
int *ptr = (int*)func(1);
cout << *ptr << std::endl; // print the int value
delete ptr;
double *ptr2 = (double*)func(2);
cout << *ptr2 << std::endl; // print the double value
delete ptr2;
char *ptr3 = (char*)func(3);
cout << ptr3 << std::endl; // print the string
delete[] ptr3;
getchar();
return 0;
}
If you can use C++17, you can easily solve it by using a std::variant instead of a void *:
#include<iostream>
#include<string>
#include<variant>
std::variant<int, double, std::string, void *> func(int a) {
if (a == 1) {
int param = 5;
return param;
} else if (a == 2) {
double param = 5.5;
return param;
} else if (a == 3) {
std::string param = "hello";
return param;
} else {
return nullptr;
}
}
int main() {
std::visit([](auto v) {
std::cout << v << std::endl;
}, func(3));
}
See it up and running on wandbox.
In C++11/14 you can do the same with a tagged union. The basic idea is that what you return contains enough information so that the caller can get out of it the original type.
Alternatives exist.
As an example, you could erase the type and return a pair that contains both the original (erased) variable and a pointer to function filled with an instantiation of a function template. The latter will be able to reconstruct the original variable from a void * for it knows its type.
Well, pretty much a great machinery you can avoid to use with a tagged union or a std::variant (more or less a type-safe version of a tagged union at the end of the day).
What you're returning is the address of a local variable. That variable goes out of scope when the function returns, meaning that the memory it was using could be reused. Attempting to dereference that pointer (i.e. access the memory it points to) invokes undefined behavior.
Even if you were returning a valid pointer, the fact that your function returns a void * means that any type information regarding what that pointer was pointing to is lost. You could print one or more bytes starting at that address, but it won't tell you what the original type was.
Even if that pointer were valid, you simply can't have enough information to force safely a cast to something and then print it.
No information of its size, no information of its internal layout. So,you simply can not print what's pointed by a void*, unless you have some information prepared by hand somewhere, and force a static_cast to the known type.
For example:
double x = 1.2;
int y = 5;
int f(void** output) {
static int x;
if ( x++ ) {
*output = &x;
return 1;
}
*output = &y;
return 2;
}
...
void* out;
int r = f(&out);
if ( r == 1 ) cout << *(static_cast<double*>(out));
else if ( r == 2 ) cout << *(static_cast<int*>(out));
So..I'm testing a function with assert: (The value of pBola1 is 1)
assert(BomboTest.TreureBola(1)==pBola1);
BomboTest.TreureBola it's a function that returns a random number (in this case has to return 1) of a list.
cBola* cBombo::TreureBola(int num)
{
int posicio_aleatoria;
posicio_aleatoria= rand() % (num);
return(Boles.TreureElement(posicio_aleatoria));
}
And TreureElement it's a function that returns an element of a dynamic list knowing the position of the element that you want to extract(in this case returns 'retorn' which is 1)
cBola* cLlista::TreureElement(int posicio)
{
int i;
cBola* recorreLlista;
cBola *retorn;
recorreLlista=primer;
retorn = primer;
i=0;
if (posicio == 0)
{
primer = (*primer).getSeguent();
}
else
{
// Busquem la posiciĆ³ //
while(i < posicio)
{
recorreLlista= retorn;
retorn = (*retorn).getSeguent();
i++;
}
(*recorreLlista).setSeguent( (*retorn).getSeguent() );
}
numElements--;
return retorn;
}
And I don't know why but the assert fails. I can see the value returned by TreureElement because I have the pointer 'retorn' but I can't know the value returned by TreureBola..There is some way to see that value returned by TreureBola in the debugger?
PD:I'm using visual studio 2010
Just create a local
cBola* pTemp = BomboTest.TreureBola(1);
assert(pTemp==pBola1);
You could look in the dissasembly and inspect the return registry, but this seems like overkill. The above is the correct approach and others will thank you in the future, when they encounter the same problem.
You can always temporarily change
assert(BomboTest.TreureBola(1)==pBola1);
to`
auto tmp=BomboTest.TreureBola(1);
assert(tmp==pBola1);
and place a breakpoint on the first line.
I would write a small wrapper around assert to use instead:
template <typename T>
void compare(const T& lhs, const T& rhs)
{
if (lhs != rhs)
cout << "The values were not the same! " << lhs << " vs. " << rhs << endl;
assert(lhs == rhs);
}
This will still call assert, but first you'll get some (hopefully) useful output first.
So instead of calling:
assert(BomboTest.TreureBola(1)==pBola1);
You would call:
compare(BomboTest.TreureBola(1), pBola1);
This has an added benefit that you can place a breakpoint here and see see what TreureBola returned in the debugger, too.
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
}
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;
}
}