Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tag_invoke with non const ref to json value #1068

Open
mous16 opened this issue Jan 21, 2025 · 1 comment
Open

tag_invoke with non const ref to json value #1068

mous16 opened this issue Jan 21, 2025 · 1 comment

Comments

@mous16
Copy link

mous16 commented Jan 21, 2025

In my code I would need to extract non-const pointers to underlying json values through functions such as if_int64 during JSON to C++ object conversion.
I see that all the if_ function implement a non-const overload, so I guess it's feasible.
My problem arises when i try to implement my custom tag_invoke.

The tag_invoke function for value_to usage has this form:

T tag_invoke( const value_to_tag< T >&, const value& );

I would need an overload where the value argument is passed as non-const reference, to be able to obtain non-const pointer to inner objects.
There is a specific reason why this overload is not present?

Delving into possible UB, I played with const_cast and I was unable to trigger any problem in code like the following:

class MyType {

    private:
    int64_t * my_inner_value;

    public:

    MyType(int64_t * my_inner_value) : my_inner_value{my_inner_value} {}

    const int64_t & get_my_inner_value() const { return *my_inner_value; }
    void set_my_inner_value(const int64_t & value) { *(this->my_inner_value) = value; }
};

MyType tag_invoke(json::value_to_tag<MyType>, const json::value & v)
{
    auto& o = const_cast<json::object&>(v.as_object());

    return { o.at(myKey).if_int64() };
}

But that smells like a possible bug in my program.
To my surprise, checking the code of non-const accessor for internal pointers, I saw that the same const cast approach is used.
Can I assume that my implementation will not trigger UB and will be reliable?

@grisumbras
Copy link
Member

You can const_cast from a const pointer or reference, if you know that the referenced/pointed to object is not in fact const. Otherwise it would be UB. So,

value jv = ...
value_to<MyType>(jv);

is not UB, but

value const jv = ...
value_to<MyType>(jv);

is.

Anyways, your tag_invoke overload stores a pointer to a potentially temporary object. This IMO has a higher chance of causing undefined behaviour. Can you explain why you need to do this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants