次の非型テンプレートがあります。
template<size_t MAX_SIZE>
struct Path{
struct Point{
float x;
float y;
}
};
Point segment[MAX_SIZE];
};
ここで2つの異なるパスを宣言した場合、構造体は同じ構造であるがタイプが異なるため、異なるセグメントの要素を相互に割り当てることはできません。
Path<10> path_a ;
Path<30> path_b ;
path_a.segment[0].x = 1;
path_a.segment[0].y = 2;
path_b.segment[0] = path_a.segment[0]; // <- error C2679 in Visual Studio)
もちろん、ポイントとパスの定義を分離すると、割り当ては機能します。
struct Point{
float x;
float y;
};
template<size_t MAX_SIZE>
struct Path{
Point segment[MAX_SIZE];
};
しかし、それは私が望んでいることではありません(これは単なるMWEです)。そのため、コピー代入演算子をオーバーロードして機能させるにはどうすればよいか疑問に思いました。私は多くの変種を試しました、例えば:
template<size_t MAX_SIZE>
struct Path{
struct Point{
float x;
float y;
template<size_t OTHER_SIZE>
Point & operator = (const typename Path<OTHER_SIZE>::Point & that)
{
x = that.x;
y = that.y;
return *this;
}
};
Point segment[MAX_SIZE];
};
しかし、私はいつも同じエラーを受け取ります。だから私の質問は:構造体のレイアウトを変更せずに次のフォームの割り当てを可能にする方法で=をオーバーロードすることは可能ですか?
path_b.segment[0] = path_a.segment[0];
はい、そのような設定は可能です。コアには、すべてのタイプを受け入れる代入演算子テンプレートが必要です。
template<class T>
Point & operator = (const T & that)
基本的な解決策としては、これで十分です。これで、メンバーがx
ありy
互換性のあるタイプのすべてのタイプで機能し、そうでないタイプに対して(通常は)醜いエラーメッセージが生成されます。
それで十分であれば、完了です。
代入演算子の他のオーバーロードがある場合は、テンプレート1を選択的に無効にすることをお勧めします。このためには、Point
クラスをインストルメント化し、SFINAEを使用する必要があります。
template<size_t MAX_SIZE>
struct Path{
struct Point{
float x;
float y;
struct EnableAssignment {};
};
Point segment[MAX_SIZE];
};
インストルメンテーションは次のように使用されます。
template<class T, class U = typename T::EnableAssignment>
Point & operator = (const T & that)
上記のコードは、C ++ 11でのみ導入された関数テンプレートのデフォルトのテンプレート引数を使用しています。その前に、他の方法でSFINAEを呼び出す必要があります。
template <class L, class R>
struct SfinaeThenRight
{
typedef R type;
};
template <class T>
typename SfinaeThenRight<typename T::EnableAssignment, Point&>::type operator = (const T & that)
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加