C++ (具体的には、MinGW の g++ の実装) が混乱しています。任意の数の任意のタイプの要素を含む数学的 Vector クラスがあります。要素のタイプと要素の数は、コンパイル時に指定されます。
Vector クラスは、そのコンストラクターの 1 つと、私が「サイズ変更」オペレーターと呼んでいるものとの間で混乱しています。サイズ変更演算子を使用すると、プログラマはあるサイズのベクトルを別の任意のサイズのベクトルにキャストできます。キャスト ベクトルに基本ベクトルよりも多くの要素がある場合、1 でパディングされます。実装は次のとおりです。
/*
* resize operator:
* T is the type of element the base vector holds
* N is the number of elements the base vector holds
* rN is the size of the new vector
*/
template<typename T, unsigned int N, unsigned int rN>
operator Vector<T, rN>() const
{
Vector<T, rN> resize;
for (unsigned int i = 0; i < rN; i++)
{
resize[i] = i < N ? this->elements[i] : 1;
}
return resize;
}
vector クラスには、要素 (T 型でなければならない) の任意の組み合わせと任意の数の Vector (任意の数の要素を含むことができ、T 型でなければならない) をいくつでも取ることができるタイプセーフな可変引数コンストラクタもあります。提供されたベクトルの要素の数に追加された裸の要素の数が、構築するベクトルに含まれる要素の数と等しい限り。
したがって、これは有効です。
vec3 foo(vec2(1, 2), 3);
しかし、これではありません。
vec3 bar(vec4(1, 2, 3, 4), 5);
カウンターを使用してすべての要素を再帰することにより、コンパイル時に適切な数の要素が提供されていることを確認します。次に、静的アサーションを使用して、カウンターがベクトルに含まれる要素の数になるようにします。次のコードを除いて、これは通常うまくいきます。
vec4 bar(1, 2, 3, 4);
(vec3) bar; //PROBLEM HERE
何が起こっているかというと、実際にはサイズ変更演算子を呼び出す必要があるときに、(vec3) bar が可変長コンストラクターを要求していると C++ が考えていることです。それらを明示的にしようとしましたが、うまくいきませんでした。可変引数コンストラクターではなく上記のコードがある場合、C++ がサイズ変更演算子を使用するようにするにはどうすればよいですか?
要するに、これを使用するように C++ に指示する方法は次のとおりです。
//resize operator
template<typename T, unsigned int N, unsigned int rN>
Vector<T, N>::operator Vector<T, rN>();
これの代わりに:
//constructor
template<typename T, unsigned int N, typename ... Args>
Vector<T, N>::Vector(Args ... arguments);
このコードがある場合:
(vec3) someVec4;
明確でない場合のために、vec3 と vec4 は次のように定義されています。
typedef Vector<float, 3> vec3;
typedef Vector<float, 4> vec4;
編集:
ニュース、皆さん!static_cast(someVec4) を使用しても、vec4 引数を使用して vec3 コンストラクターを呼び出します。どうしてか分かりません。
別の編集:
コンストラクターを明示的にすると、暗黙的なキャストは機能しますが、明示的なキャストは機能しません。つまり、このコードは機能します。
vec3 foo = someVec4;
しかし、このコードでも静的アサーション エラーが発生します。
vec3 foo = static_cast<vec3>(someVec4);
可変引数コンストラクターを明示的に宣言したため、基本的に意味がありません。したがって、そこで呼び出すべきではありません。
また、リクエストに応じて、ここにSSCCEがあります
これのTL;DRバージョンは、型キャスト演算子を明示的に呼び出そうとするとコードが明示的なコンストラクターを呼び出しますが、暗黙的に呼び出そうとすると呼び出しません。