'new auto' 在 C++ 构造函数中
'new auto' in C++ constructor
C++ 能否以某种方式接受 'auto' 的这种用法?:
class A {
public:
A(): m_member(new auto)
{
[...]
}
private:
BoringToTypeType *m_member;
}
目的是通过简化 A 的构造函数中的成员元素初始化来利用 'auto'。实际上,代码会引发以下错误:
new expression for type 'auto' requires a constructor argument.
如果你不想重复那个类型名称,你可以添加一个私人别名:
class A {
using mem_t = BoringToTypeType;
public:
A(): m_member(new mem_t)
{
[...]
}
private:
mem_t *m_member;
}
当然,在实际代码中,大多数情况下你应该使用 std::unique_ptr
或类似的东西而不是原始指针。
new auto(...)
从 (...)
内部传递的表达式推导出结果指针的类型。在您的特定情况下,没有什么可以推断出来的。
您有几个选择:
m_member(new auto(x))
,其中 x
是 BoringToTypeType
.
类型的表达式
m_member(new std::remove_pointer_t<decltype(m_member)>)
,这肯定不是对 BoringToTypeType
.
的改进
如果您不介意定义一个额外的辅助函数,这里有一个替代解决方案:
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;
};
在这种情况下,T
纯粹用于类型推导目的。 m_member
必须重复两次,但您可以避免以这种方式输入其类型。
Simple tests on godbolt.org 表明 newer
不会产生任何额外开销。
将 m_member 设为 std::unique_ptr
,您将可以访问 element_type
。所以代码看起来像:
class A {
public:
A(): m_member(std::make_unique<decltype(m_member)::element_type>(...))
{
[...]
}
private:
std::unique_ptr<BoringToTypeType> m_member;
};
这是否是一种改进值得商榷 - 但如果 BoringToTypeType
更复杂,它会有所帮助。
您可以定义自动构造函数 class - 在转换时创建新对象的想法需要指向此对象 (working demo):
首先这个自动构造函数(或者可能是任何构造函数)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;
};
很难使用这个 class w/o 辅助 make 函数:
template <typename ...T>
auto makeAuto(T&&... a)
{
return AutoConstructor<T...>(std::forward<T>(a)...);
}
那么-这样的"magic"是可能的:
long&& d = 7;
int* a = makeAuto();
S *s = makeAuto(std::ref(*a), 2, std::make_unique<float>(3), std::move(d));
假设 S 有 c-tor S(int& a, const int& b, std::unique_ptr<float> c, long d)
总结一下 - 我提供的这段代码非常容易使用 - 但我怀疑在代码中到处都有 makeAuto
调用...
是个好习惯
C++ 能否以某种方式接受 'auto' 的这种用法?:
class A {
public:
A(): m_member(new auto)
{
[...]
}
private:
BoringToTypeType *m_member;
}
目的是通过简化 A 的构造函数中的成员元素初始化来利用 'auto'。实际上,代码会引发以下错误:
new expression for type 'auto' requires a constructor argument.
如果你不想重复那个类型名称,你可以添加一个私人别名:
class A {
using mem_t = BoringToTypeType;
public:
A(): m_member(new mem_t)
{
[...]
}
private:
mem_t *m_member;
}
当然,在实际代码中,大多数情况下你应该使用 std::unique_ptr
或类似的东西而不是原始指针。
new auto(...)
从 (...)
内部传递的表达式推导出结果指针的类型。在您的特定情况下,没有什么可以推断出来的。
您有几个选择:
m_member(new auto(x))
,其中x
是BoringToTypeType
. 类型的表达式
m_member(new std::remove_pointer_t<decltype(m_member)>)
,这肯定不是对BoringToTypeType
. 的改进
如果您不介意定义一个额外的辅助函数,这里有一个替代解决方案:
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;
};
在这种情况下,T
纯粹用于类型推导目的。 m_member
必须重复两次,但您可以避免以这种方式输入其类型。
Simple tests on godbolt.org 表明 newer
不会产生任何额外开销。
将 m_member 设为 std::unique_ptr
,您将可以访问 element_type
。所以代码看起来像:
class A {
public:
A(): m_member(std::make_unique<decltype(m_member)::element_type>(...))
{
[...]
}
private:
std::unique_ptr<BoringToTypeType> m_member;
};
这是否是一种改进值得商榷 - 但如果 BoringToTypeType
更复杂,它会有所帮助。
您可以定义自动构造函数 class - 在转换时创建新对象的想法需要指向此对象 (working demo):
首先这个自动构造函数(或者可能是任何构造函数)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;
};
很难使用这个 class w/o 辅助 make 函数:
template <typename ...T>
auto makeAuto(T&&... a)
{
return AutoConstructor<T...>(std::forward<T>(a)...);
}
那么-这样的"magic"是可能的:
long&& d = 7;
int* a = makeAuto();
S *s = makeAuto(std::ref(*a), 2, std::make_unique<float>(3), std::move(d));
假设 S 有 c-tor S(int& a, const int& b, std::unique_ptr<float> c, long d)
总结一下 - 我提供的这段代码非常容易使用 - 但我怀疑在代码中到处都有 makeAuto
调用...