19
T *t; //T is an implementation detail
t = new T; //want to avoid naming T to allow for flexibility
t = new decltype(*t); //error: cannot use 'new' to allocate a reference
t = new std::remove_reference<decltype(*t)>::type(); //clunky

This answers why decltype(*t) returns T & and not T.

I can put my last line into a macro, but that seems suboptimal. Is there a better solution than what I have so far? Does this belong on Code Review?

Community
  • 1
  • 1
nwp
  • 9,623
  • 5
  • 38
  • 68
  • 1
    +1, This certainly belongs to SO. – 101010 Aug 14 '14 at 13:36
  • 4
    The question as to whether this belongs on Code Review or not belongs on Meta. :) –  Aug 14 '14 at 13:38
  • 11
    In C++11 you shouldn't be working with raw pointers. Use [`std::unique_ptr`](http://en.cppreference.com/w/cpp/memory/unique_ptr). Don't write `new` either, implement your own [`std::make_unique`](http://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique) (or use a compiler like GCC 4.9 or the lastest MSVC++ that already have it) and use that. – Robert Allan Hennigan Leahy Aug 14 '14 at 13:43
  • 2
    The common approach to avoid naming `T` is to provide an appropriate `typedef` that can be adjusted by the library owner. I don't see the point of *hiding* types everywhere... then again I don't believe in the *almost always auto* preaching. – David Rodríguez - dribeas Aug 14 '14 at 13:55
  • Actually, in isolation, `*t` _is_ a `T` :) You get an lvalue back and it's not a reference. `decltype` ruins that for you though – Lightness Races in Orbit Aug 14 '14 at 15:05

2 Answers2

11

If they're on the same line, you can use auto to only name T once:

auto t = new T;

Otherwise, you could create a small function template:

template <class T>
void do_new(T * &p) {
  p = new T;
}


// Usage:
int main()
{
  T *t;
  do_new(t);
}

As @MadScienceDreams pointed out, you can extend this to allow non-default constructors:

template <class T, class... Arg>
void do_new(T * &p, Arg &&... arg) {
  p = new T(std::forward<Arg>(arg)...);
}


// Usage:
int main()
{
  T *t;
  do_new(t);
  std::string *s;
  do_new(s, "Abc");
}
Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
6

std::remove_pointer<decltype(t)>::type is more expressive/clear.

You can also use a local typedef if this is repeated several times, or would make a certain line grow excessively long/complicated.