API のマイナーな変更後、テンプレートの混乱の途中で突然現れたため、特定するのに何年もかかった奇妙なあいまいさに出くわしました。
次の例では、コンストラクターを呼び出すさまざまな方法を探っています (またはそう思っていました)。そのうちのいくつかは、私にはまったくわかりません。それらのすべてで、 type のオブジェクトを宣言しようとしています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
}
2 番目と 4 番目の例では、オブジェクトではなく関数ポインターを宣言しているように見えますが、これにはいくつか疑問があります。
V(v)
がオブジェクトではなく型として解釈されるのはなぜA a(V(v))
ですか?- 解釈されたもの
V(v)
へのキャストバックはどのように異なりますか?(V)V(v)
- コンパイラがキャスト自体を推測できないのはなぜですか?
- 6の二重括弧
((...))
には意味的な意味がありますか、それともパーサーのあいまいさを解消するのに役立つだけですか? それがどのように優先順位の問題になるのかわかりません。 V(v)
オブジェクトではなく Type に評価される場合、なぜ 12 で合法ではないA a(V(v), V(v))
のですか?- スカラー値も追加すると、8 から 11 でコンパイラがもう一方もオブジェクトであることに突然気付くのは面白いことです。
- あいまいさを再現する構文を見逃していませんか? 他に紛らわしい事例を知っていますか。
- GCC は、そこに問題がある可能性があることを警告するべきではありませんか? Clangはそうします。
ありがとう、