'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)),其中 xBoringToTypeType.

  • 类型的表达式
  • 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 调用...

是个好习惯