2017-01-03 127 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電話...