Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Comparing typeid pointers

Tags:

c++

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?

like image 923
StackedCrooked Avatar asked Nov 18 '16 09:11

StackedCrooked


1 Answers

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.

like image 63
Nir Friedman Avatar answered Sep 22 '22 23:09

Nir Friedman