Reputation: 1694
Can C++ somehow accept this use of 'auto'?:
class A {
public:
A(): m_member(new auto)
{
[...]
}
private:
BoringToTypeType *m_member;
}
The purpose is to take advantage of 'auto' by simplifying the member element initialisation in A's constructor. As it is, the code raises the following error:
new expression for type 'auto' requires a constructor argument.
Upvotes: 4
Views: 2905
Reputation: 24412
You might define auto constructor class - the idea it to have new object created when casting needed to pointer to this object (working demo):
First this auto-constructor (or maybe any-constructor) class:
#include <tuple>
#include <utility>
template <typename ...T>
class AutoConstructor
{
public:
template <typename ...U>
AutoConstructor(U&&... a) : params(std::forward<U>(a)...) {}
template <typename U>
operator U* ()
{
return construct<U>(std::index_sequence_for<T...>{});
}
private:
template <typename U, std::size_t ...I>
U* construct(std::index_sequence<I...>)
{
return new U(std::forward<T>(std::get<I>(params))...);
}
std::tuple<T...> params;
};
It would be hard to use this class w/o helper make function:
template <typename ...T>
auto makeAuto(T&&... a)
{
return AutoConstructor<T...>(std::forward<T>(a)...);
}
Then - such "magic" is possible:
long&& d = 7;
int* a = makeAuto();
S *s = makeAuto(std::ref(*a), 2, std::make_unique<float>(3), std::move(d));
Assuming S has c-tor S(int& a, const int& b, std::unique_ptr<float> c, long d)
Just to summarize - this piece of code I presented is quite easy to use - but I doubt it would be good habit to have everywhere in the code makeAuto
calls...
Upvotes: 1
Reputation: 28987
Make m_member a std::unique_ptr
, and you will get access to element_type
. So the code looks like:
class A {
public:
A(): m_member(std::make_unique<decltype(m_member)::element_type>(...))
{
[...]
}
private:
std::unique_ptr<BoringToTypeType> m_member;
};
It's debatable whether that's an improvement - but it helps if BoringToTypeType
is more complex.
Upvotes: -1
Reputation: 93274
new auto(...)
deduces the type of the resultant pointer from the expression passed inside (...)
. In your particular case there's nothing that can be deduced.
You have a few options:
m_member(new auto(x))
, where x
is an expression of type BoringToTypeType
.
m_member(new std::remove_pointer_t<decltype(m_member)>)
, which is most certainly not an improvement over BoringToTypeType
.
If you don't mind defining an additional helper function, here's an alternative solution:
template <typename T, typename... TArgs>
auto newer(T*, TArgs&&... args)
{
return new T(std::forward<TArgs>(args)...);
}
class A
{
public:
A(): m_member(newer(m_member, 12))
{
}
private:
int *m_member;
};
In this case T
is used purely for type deduction purposes. m_member
has to be repeated twice, but you avoid typing out its type this way.
Simple tests on godbolt.org show that newer
does not incur any additional overhead.
Upvotes: 7
Reputation: 65620
If you don't want to repeat that type name, you can add a private alias:
class A {
using mem_t = BoringToTypeType;
public:
A(): m_member(new mem_t)
{
[...]
}
private:
mem_t *m_member;
}
Of course, in real code you should use std::unique_ptr
or similar instead of raw pointers in most cases.
Upvotes: 6