2012-11-06 42 views
4

如何讓編譯器創建臨時對象,在未定義函數時對其使用默認構造函數?避免最令人頭痛的解析

struct B {}; 
template<class T> struct C {}; 

template<class T,class T1> 
struct A 
{ 
    A(const T& t,const T1& t1): m_t(t),m_t1(t1) 
    { 
    std::cout << __PRETTY_FUNCTION__ << "\n"; 
    } 

    T m_t; 
    T1 m_t1; 
}; 


int main() { 
    A< B , C<B> > a0(B() , C<B>()); // Function definition 
    A< B , C<B> > a1(B b , C<B> c); // dito, *at least A(const T& t,const T1& t1) not called 
} 
+2

使用更多括號,比如'(B())',或者在C++ 11中使用'B {}'。 –

+1

@ R.MartinhoFernandes:爲什麼這是一個評論? :( –

回答

3
A< B , C<B> > a0((B()), (C<B>())); 
//    ^^^ ^

與外括號,每個參數只能是一個表達式,而不是一個聲明。

實際上,您只需要這樣做就可以將一個的參數設置爲防止整行被解析爲表達式。你可以選擇哪個,或者兩者兼而有之。

不要忘記在代碼旁邊寫一個註釋,說明「額外」括號有很好的理由,否則上帝知道有人會在「輕微」VCS提交中將他們刪除。

5

你可以用你的論據之一在額外的括號從被解析爲函數聲明停止:

A< B , C<B> > a0((B()) , C<B>()); 

甚至更​​好,如果你有機會到C++編譯器11使用大括號初始化:

A< B , C<B> > a0{ B() , C<B>() }; 
5

兩種方式:

  1. Intialise通過分配:

    auto a0 = A<B, C<B>>(B(), C<B>()); 
    

    注意這改變的語義,因爲它需要一個複製或移動構造函數可用於類型(儘管這將被省略,因此生成的代碼是一樣的)。

  2. 使用周圍至少有一個參數多個括號:

    A<B, C<B>> a0((B()), C<B>()); 
    

無論是作品。我更喜歡第二種方式,但它可能變得不可讀,「冗餘」的括號會讓不熟悉這種行爲的人感到驚訝。