我剛剛遇到了一個奇怪的含糊不清的問題,這個問題花了我很多時間來隔離,因爲它在API更改後突然出現在某些模板混亂的中間。作爲構造函數參數的構造函數調用將聲明作爲函數指針進行評估
以下示例探討調用構造函數的不同方法(或者我認爲的),其中一些對我來說很模糊。在他們所有人中,我試圖聲明A
類型的對象。
#include <vector>
#include <cstdlib>
#include <iostream>
#include <typeinfo>
using namespace std;
// just a dummy class to use in the constructor of the next class
struct V {
V(const std::vector<size_t> &){}
};
// the class we are interested in
struct A{
A(const V &){}
A(int, const V &){}
A(const V &, int){}
A(const V &, const V &){}
};
// a dummy function to delegate construction of V
V buildV(std::vector<size_t> &v){ return V(v); }
int main(){
std::vector<size_t> v = {1024,1024};
V vw(v);
// I am using macros to make the constructor argument more visible
#define BUILD_A(X) { A a(X); std::cerr << typeid(a).name() << std::endl; }
#define BUILD_A2(X,Y) { A a(X, Y); std::cerr << typeid(a).name() << std::endl; }
// All of the following call the constructor of A with different parameters
// the comment on the right shows the type of the declared a
/* 1 */ BUILD_A(vw) // object
/* 2 */ BUILD_A(V(v)) // function pointer
/* 3 */ BUILD_A(v) // object
/* 4 */ BUILD_A(std::vector<size_t>()) // function pointer
/* 5 */ BUILD_A((V)V(v)) // object
/* 6 */ BUILD_A((V(v))) // object
/* 7 */ BUILD_A(buildV(v)) // object
/* 8 */ BUILD_A2(10,V(v)) // object
/* 9 */ BUILD_A2(V(v),10) // object
/* 10 */ BUILD_A2(vw,V(v)) // object
/* 11 */ BUILD_A2(V(v), vw) // object
/* 12 */ //BUILD_A2(V(v), V(v)) // doesn't compile
/* 13 */ BUILD_A2(V(v), (V)V(v)) // object
}
第二和第四實施例似乎聲明一個函數指針,而不是一個對象,這引起了幾個問題:
- 爲什麼
V(v)
解釋爲類型,而不是爲A a(V(v))
對象? - 如何解析
V(v)
到(V)V(v)
解釋不同? - 爲什麼編譯器無法推斷出演員本身?
- 6中的雙括號
((...))
是否具有語義含義,還是僅僅有助於消歧解析器?我不明白這可能是一個優先問題。 - 如果
V(v)
的計算結果爲Type而不是對象,爲什麼A a(V(v), V(v))
在12中不合法? - 有趣的是,添加一個標量值突然讓編譯器意識到另一個對象也在8到11之間。
- 我是否錯過任何會重現歧義的語法?你知道任何其他令人困惑的情況嗎?
- 不應該GCC警告我那裏可能有問題嗎?鏗鏘。
感謝,
請參閱http://en.wikipedia.org/wiki/Most_vexing_parse – JBentley 2013-04-11 19:05:29