Question

Let me brief the actual scenario first :

I have created a class template called error<T> which holds the type T and error related variables.
The constructor is like so

error(T&&,..other_params...)   

and there is a utility function that generates this which is defined as so

template<typename T>
make_error(T&& val_T,..other_params..)
{return error<T>(std::forward<T&&>(val_t),..other_params..);}

i use this type as return type instead of just the type T. basically it just wraps the type with error info.

it has a getter which gets the value of the type contained:

T get()
{ return val_T_int;}

where val_T_int is initalized with the val_t above.
When i use a move only type this get gives an error saying delete copy constructor being used.

Q1. why does it say this?why wont it move construct the value?i.e i have to explicitly use std::move() on the return value.

Q2. if Q1 is not possible then how would i enable such a feature where the user, instead of returning a type would return this error .i could not use boost::optional because it needs the type to be copy constructible?

my compiler : minGW GCC 4.8.2 on windows 7.

for example :

class B //a move only type
{
    B( const B& )=delete;
    B& operator=( const B& ) = delete;
public:
    B( B&& )
    {
        std::cout << "B&&\n";
    }

    B& operator=( B&& )
    {
        std::cout << "B=\n";
            return *this; 
    }
    B(){ std::cout << "B()\n"; }
};

struct error  //the other parts are stripped of for simplicity.
{
    B get()
    {
        return std::move(b);
    }
private :
    B b{};// B is a move only type.
};

error er{};
er.get(); //error:use of deleted function B(const B&)!.

what am i not understanding here?. Thanks for reading.

P.S this is close but i dont understand the reason for the local variable.

this and this also dint help

Was it helpful?

Solution

Take a look at the following code. If the get method would move the string out of the member variable, what should be the value of t?

error e = make_error(std::string{"foobar"});
std::string s = e.get();
std::string t = e.get();

You can return a reference to the member variable. It might look as follows:

const T& get() const { return val_T_int; }

The problem with that solution is, that you can't use it with non-copyable types the following way:

std::unique_ptr<...> result = make_error(...).get();

However, you can use rvalue-references for this to solve this problem. If you declare get in the following way, the function can only be used on temporaries (and explicitly moved objects). So it's fine to move the member variable out of the object.

T get() && { return std::move(val_T_int); }

OTHER TIPS

Your get() wants to return a copy, so it need the copy-ctor. If you'd move the internal value val_T_int to the returned value, you'd invalidate val_T_int. You couldn't access its value afterwards which is probably not what you want.

One solution that comes to mind: Don't return a value, just allow (const) access:

const T& get() const
{
    return val_T_int;
}

If you also want/need non-const access, add a second overload:

T& get()
{
    return val_T_int;
}

which allows users of your class to even modify val_T_int, e.g. er.get() = 42;.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top