c++templatesdecltype

How do I use decltype to get the type instead of a reference to the type?


In the following case, decltype always returns a reference to the type:

template <typename T>
struct MyStruct
{
};

auto getMyStruct()
{
    static MyStruct<int> one;
    static MyStruct<double> two;

    if constexpr ((1103515245U ^ 0x1103515245) > 0x0041389155)
        return &one;
    else
        return &two;
}

int main(int argc, char* argv[])
{   
    auto* p = getMyStruct();
    decltype(*p); // DECLTYPE WILL ALWAYS BE REF
}

When I do decltype(*p), I want the type, not a type reference. std::remove_reference can't be used, I don't know what to do.


Solution

  • Using decltype with operator* (AKA the indirection operator) indeed yields a reference type. This is because operator* returns an "lvalue referring to the object", and decltype yields a T& for lvalues ("if the value category of expression is lvalue, then decltype yields T&").

    But the purpose of std::remove_reference_t is exactly to remove the reference and get the type referred to.

    In your case, you can use it as following:

    #include <type_traits>  // required for std::remove_reference_t
    
    // ...
    
    std::remove_reference_t<decltype(*p)> a;
    

    The type of a will be MyStruct<int> here.

    Live Demo (Godbolt)

    Note that if the type of a was a reference, the line above would not compile in the demo, because a reference must be initialized (and so e.g. decltype(*p) a; would not compile).