xuhdev
xuhdev

Reputation: 9333

C++11 decltype: How to declare the type that a pointer points to?

I have the following code:

#include <memory>

int main()
{
    int* a = new int(2);

    std::unique_ptr<decltype(*a)> p(a);
}

which leads to these error message:

In file included from a.cpp:1:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/memory:81:
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/unique_ptr.h:138:14: error: '__test' declared as a pointer to a reference of type 'int &'
          static _Tp* __test(...);
                    ^
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/unique_ptr.h:146:35: note: in instantiation of member class 'std::unique_ptr<int &,
      std::default_delete<int &> >::_Pointer' requested here
      typedef std::tuple<typename _Pointer::type, _Dp>  __tuple_type;
                                  ^
a.cpp:7:35: note: in instantiation of template class 'std::unique_ptr<int &, std::default_delete<int &> >' requested here
    std::unique_ptr<decltype(*a)> p(a);
                                  ^
In file included from a.cpp:1:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/memory:81:
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/unique_ptr.h:227:33: error: 'type name' declared as a pointer to a reference of type 'int &'
               is_convertible<_Up*, _Tp*>, is_same<_Dp, default_delete<_Tp>>>>
                                       ^
a.cpp:7:35: note: in instantiation of template class 'std::unique_ptr<int &, std::default_delete<int &> >' requested here
    std::unique_ptr<decltype(*a)> p(a);
                                  ^
2 errors generated.

I understand the reason is that the unique_ptr template expects type int, but decltype(*a) gives int&. In the case that int is a very long and complicated type, how can I make this code work with decltype?

Upvotes: 5

Views: 2736

Answers (2)

Michael Anderson
Michael Anderson

Reputation: 73490

You can use a typedef inside a templated class and then use template specialisation, like this

template<typename T> struct unref {
  typedef T raw;
};
template<typename T> struct unref<T&> { 
  typedef T raw;
};

int main() {
    int* a = new int(2);
    std::unique_ptr<unref<decltype(*a)>::raw> p(a);
}

Upvotes: 5

Pradhan
Pradhan

Reputation: 16737

Use std::decay_t. This is the conversion that is applied when you pass an argument to a function by value.

Upvotes: 14

Related Questions