2017-01-03 199 views
3

罐体C++莫名其妙地接受这个使用“自动” ?:的“新汽车” ++构造

class A { 
    public: 
     A(): m_member(new auto) 
     { 
       [...] 
     } 

    private: 
     BoringToTypeType *m_member; 
} 

的目的是通过简化在A的构造函数中成员元素初始化利用“自动”的。正因为如此,该代码会引发以下错误:

new expression for type 'auto' requires a constructor argument. 

回答

7

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不会产生任何额外的开销。

+0

第二种形式,我会考虑在C作为惯用++,如'的PVAr = malloc的(*的sizeof的PVAr);'是C.仅有一个正切想。 ** + 1 **。 – StoryTeller

+0

@StoryTeller:不幸的是,我很快就按下了“答案”,因为'decltype(m_member)'评估为指针类型......指针必须以某种方式被移除。 –

+0

'decltype(* m_member)'怎么样?那里有得救的机会吗?或者,被诅咒的'decltype'扣除规则是否将其评估为参考?无论什么优秀的答案。 – StoryTeller

5

如果你不想重复类型的名字,你可以添加一个私有别名:

class A { 
    using mem_t = BoringToTypeType; 
    public: 
     A(): m_member(new mem_t) 
     { 
       [...] 
     } 

    private: 
     mem_t *m_member; 
} 

当然,在实际的代码你应该在大多数情况下使用std::unique_ptr或类似的,而不是原始指针。

-1

让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比较复杂。

0

您可以定义自动构造类 - 铸造需要指向这个对象(working demo),当它有新的对象创建的想法:

首先这个自动构造函数(或者任何构造函数)类:

#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; 
}; 

这将是很难使用这个类W/O助手化妆功能:

template <typename ...T> 
auto makeAuto(T&&... a) 
{ 
    return AutoConstructor<T...>(std::forward<T>(a)...); 
} 

然后 - 这样的 “魔术” 是可能的:

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电话...