1

Is only the way to modify, not replace, an object stored as std::any is to declare changeable data mutable? E.g. to avoid creation and copy of class S instances:

#include <iostream>
#include <vector>
#include <any>
#include <string>
    
struct S {
    mutable std::string str;
    
    S(S&& arg) : str(std::move(arg.str)) { std::cout << ">> S moved" << std::endl; }
    S(const S& arg) : str(arg.str) { std::cout << ">> S copied" << std::endl; }
    S(const char *s) : str(s) { std::cout << ">> S created" << std::endl; }
    
    S& operator= (const S& arg) { str = arg.str; return *this; }
    S& operator= (S&& arg) { str = std::move(arg.str); return *this; }
    virtual ~S() { std::cout << "<< S destroyed" << std::endl; }
};


int main() {
    std::vector<std::any> container;

    container.emplace_back(S("Test 1"));
    
    std::any_cast<const S&>(container[0]).str = "Test 2";
    
    for (const auto& a : container) {
        std::cout << a.type().name() << ", " 
                  << std::any_cast<const S&>(a).str << std::endl;
    }
}
Swift - Friday Pie
  • 12,777
  • 2
  • 19
  • 42
  • 1
    Don't understand your problem. If I remove `mutable` and change any-cast to `any_cast`, it works: https://godbolt.org/z/ocrj4s. Does this solves your problem? Why do you any-cast to ``? – Daniel Langr Jan 07 '21 at 09:13
  • @DanielLangr something what accidently fell out of code after simplification. a const cast hidden in template parameters, std::any received was `const std::any&` – Swift - Friday Pie Jan 07 '21 at 09:20
  • "object referred by std::any" the value within a `std::any` isn't a reference, it's an object in its own right. – Caleth Jan 07 '21 at 10:18
  • @Caleth it's not located within `std::any` storage, `std::any` is functionally safer version of `void*` – Swift - Friday Pie Jan 07 '21 at 13:13
  • @Swift-FridayPie `container.emplace_back(S("Test 1"));` allocates some dynamic storage and constructs an `S`, copied from the temporary, owned by the `std::any` it is also constructing. – Caleth Jan 07 '21 at 13:18
  • 1
    To avoid the copy in the `emplace_back`, you can `container.emplace_back(std::in_place_type, "Test 1");` – Caleth Jan 07 '21 at 13:24
  • @Caleth Oh, good catch, wish I could give more credit for that. New components are.. a little new to me still after being stuck for years in C++98-locked industry. – Swift - Friday Pie Jan 08 '21 at 12:55

2 Answers2

4

You can any_cast with non-const reference:

std::any_cast<S&>(container[0]).str = "Test 2";

Demo

or

std::any a = 40;

std::any_cast<int&>(a) += 2;
std::cout << std::any_cast<int>(a) <<std::endl;

Demo

Jarod42
  • 203,559
  • 14
  • 181
  • 302
0

nope.

The issue is here.

std::any_cast<const S&>(container[0]).str = "Test 2";

you are trying to change constant data

Smit Shah
  • 108
  • 11
  • I know that, it just feels strange that `std::any` appears to be the only container with unmutable content in component library, even reference wrapper isn't, it creates impression that something is missing. – Swift - Friday Pie Jan 07 '21 at 09:00