AnArrayOfFunctions
AnArrayOfFunctions

Reputation: 3744

Is this code legal in ISO C++?

So I'm trying to implement function parameters which can be uninitialized. Here is the code which I have written. My question is if it's legal by the ISO C++ standard (version 14 if possible).

#include <iostream>
#include <typeinfo>

using namespace std;

template<typename type>

struct nzeroinittmpliteral
{
    nzeroinittmpliteral() { }    
    nzeroinittmpliteral(type arg) { d = arg; }    
    //nzeroinittmpliteral(const nzeroinittmpliteral &) = delete;    
    operator type () & { return d; }   
    operator type () && { return d; }  
    type d;
} ;

void func(bool bIsPointerValid, nzeroinittmpliteral<int *> pVar = {})
{
    if(bIsPointerValid)
    {
        cout << *pVar << endl;
    }
    else
    {
        pVar = new int;    
        *pVar = 8;    
        cout << *pVar << endl;    
        delete pVar;
    }
}

int main()
{
    func(true, { (int *)&(const int &)int{9} } );    
    func(false);
}

Upvotes: 1

Views: 137

Answers (1)

Guilherme Bernal
Guilherme Bernal

Reputation: 8293

If you want to pass a parameter that may be uninitialized, simply don't pass it, use overloading. Look:

void func(int value)
{
    cout << value << endl;
}

void func()
{
    // no 'value' was initialized here :)
    func(8);
}

Or simply give a default value to the parameter if you will provide one anyway in your body:

void func(int value = 8)
{
    cout << value << endl;
}

Besides that, you can take a look at boost::optional:

void func(boost::optional<int> optvalue = boost::none) {
    if (optvalue) {
        cout << *optvalue << endl;
    } else {
        // nothing passed
        cout << "foo" << endl;
    }
}

Directly answering your question: your code is valid.

func(true, { (int *)&(const int &)int{9} } );

By casting the temporary to a const reference, you extend its lifetime to the lifetime of the reference itself, which ends after func returns. But this is too redundant, you could simply have written:

void func(int* value) { if (value) {...} }

func(&(const int &)9);
func(nullptr);

The actual parameter being passed is your nzeroinittmpliteral and it is initialized by calling one of the constructors, always. The default constructor doesn't initialize the d member, but this is no big improvement as it is just a pointer. Using nullptr is better and removes the need for the bool parameter.

Upvotes: 4

Related Questions