Home > other >  How to call proper assignment operator of custom class inside std::variant
How to call proper assignment operator of custom class inside std::variant

Time:08-25

I have the following class:

class StackStringHolder
{
public:
    StackStringHolder& operator=(const std::string& str)
    {
        str_ = str;
        return *this;
    }
    StackStringHolder& operator=(std::string&& str)
    {
        str_ = std::move(str);
        return *this;
    }
    const std::string& get() const { return str_; }

private:
    std::string str_;
};

And I want to use it in the std::variant the following way:

int main() {
    std::variant<int, StackStringHolder> var;
    var = 5;
    std::string str = "Hello";
    var = str; // error
    var = std::move(str); // error
}

However compiler (MSVS2022) says:

error C2679: binary '=': no operator found which takes a right-hand operand of type 'std::string' (or there is no acceptable conversion)

Update, I'm sure my pieces of code enough, but as I'm asked for, here is the complete example:

#include <string>
#include <variant>

class StackStringHolder
{
public:
    StackStringHolder& operator=(const std::string& str)
    {
        str_ = str;
        return *this;
    }
    StackStringHolder& operator=(std::string&& str)
    {
        str_ = std::move(str);
        return *this;
    }
    const std::string& get() const { return str_; }

private:
    std::string str_;
};

int main() {
    std::variant<int, StackStringHolder> var;
    var = 5;
    std::string str = "Hello";
    var = str; // error
    var = std::move(str); // error

    return 0;
}

CodePudding user response:

Your var can hold either an int or a StackStringHolder, so you cannot trivially assign it with a std::string.

You can however add a converting constructor to your class StackStringHolder which accepts a std::string.
Then it can be used to convert str to StackStringHolder and assign it to var.

Your converting constructor can look something like:

StackStringHolder(std::string const& str)
    : str_(str)
{}

Now you can use:

var = str;
var = std::move(str);

CodePudding user response:

variant::operator= will invoke the constructor to construct the alternative type, so you need to provide the corresponding constructor for StackStringHolder

class StackStringHolder
{
public:
    StackStringHolder(const std::string& str) : str_(str) { }
    StackStringHolder(std::string&& str) : str_(std::move(str)) { }
}
  • Related