In this program I use typeid to check the derived type of an object:
#include <cstdint>
#include <memory>
#include <cassert>
#include <string>
#include <typeinfo>
struct Wrap
{
explicit Wrap(int64_t id) : mImpl(new Impl<int64_t>(id)) {}
explicit Wrap(std::string id) : mImpl(new Impl<std::string>(std::move(id))) {}
bool isInt64() const
{
const ImplBase& impl = *mImpl;
return (&typeid(impl) == &typeid(const Impl<int64_t>));
}
bool isString() const
{
const ImplBase& impl = *mImpl;
return &typeid(impl) == &typeid(const Impl<std::string>);
}
private:
struct ImplBase
{
virtual ~ImplBase() {}
};
template<typename T>
struct Impl : ImplBase
{
Impl(T value) :
mValue(std::move(value))
{
}
T mValue;
};
std::shared_ptr<const ImplBase> mImpl;
};
int main()
{
Wrap r1(int64_t(1));
assert(r1.isInt64());
Wrap r2(std::string("s"));
assert(r2.isString());
}
It seems to work, however, I worry that this may not work on all platforms. Also I'm not sure if I should use:
typeid(const Impl<std::string>&) // with ref
instead of
typeid(const Impl<std::string>) // without ref
in the comparison functions.
Is the above code correct? If not, then how can I fix it?
When using typeid
, it can be applied to either an expression or a type. When applied to a type, as you have:
Refers to a std::type_info object representing the type type. If type is a reference type, the result refers to a std::type_info object representing the referenced type.
http://en.cppreference.com/w/cpp/language/typeid. So it does not make any difference whether or not you use the reference. The same source goes on to say:
There is no guarantee that the same std::type_info instance will be referred to by all evaluations of the typeid expression on the same type, although std::type_info::hash_code of those type_info objects would be identical, as would be their std::type_index.
That means that comparing &typeid(impl)
to something else, could return false even when the object has the same dynamic type. So it's not such a good choice to compare their addresses. You should compare the objects themselves directly instead, i.e. just remove the &
operator from both sides, because std::type_info
(returned by typeid
) has operator==
defined.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With