Peter Lenkefi
Peter Lenkefi

Reputation: 1356

Decaying a templated type's value in C++

I'm implementing a simple variant class (mainly for practice) and I've come to a problem with type decaying. I would like to create a constructor that takes a sub-type of the variant and constructs it accordingly (case (4) here, the converting constructor).

For copying and moving, I have a helper class that contains functions like this:

static inline void copy(std::size_t old_type_id, void* old_data, void* new_data);
static inline void move(std::size_t old_type_id, void* old_data, void* new_data);

So I'm passing everything as a void* for simplicity. My converting constructor looks like this:

template <typename T>
variant(T&& v)
    : type_id{ typeid(std::decay_t<T>).hash_code() } {
    if constexpr (std::is_lvalue_reference_v<T>) {
        helper_type::copy(type_id, reinterpret_cast<void*>(&v), &data);
    }
    else {
        helper_type::move(type_id, reinterpret_cast<void*>(&v), &data);
    }
}

My idea was to check if this is a reference, because then we can only copy, otherwise move. But because v is a templated parameter, there is no automatic decaying of types, and if I try to pass a C-style string, I get errors like:

cannot convert from 'const char (*)[6]' to 'void *'

Is there a way to do this kind of conversion without specializing every decaying type?

Upvotes: 1

Views: 89

Answers (1)

Rakete1111
Rakete1111

Reputation: 49028

As @liliscent says, you need to use const void*.

This is because even though void* can accept any type of pointer, it is still bound to the rules that state that a conversion from const T* to T* is ill-formed if you don't use const_cast (which you shouldn't in this case).

Upvotes: 1

Related Questions