データメンバーのみを持つCFixedLengthString
クラステンプレートがあります。データメンバーのサイズは、テンプレートタイプの引数によって決定されます。
template<size_t _Length>
class CFixedLengthString
{
private:
char Buffer[_Length];
public:
// Has constructors, conversion operators etc.
// Listing the important ones
operator const char*();
operator = (const CFixedLengthString&);
operator = (const char*);
};
自動変換は便利です。例:
CFixedLengthString<10> buf;
buf = "SomeString";
strlen(buf);
しかし、この便利さにより、次のことが成功することもできます。
CFixedLengthString<10> buf1;
CFixedLengthString<20> buf2;
buf1 = buf2;
ここでbuf2
はconst char*
、暗黙の変換演算子を介して変換され、operator=
で呼び出されconst char*
ます。したがって、<20>
に変換され<10>
ます。
ここで重要なもの。CFixedLengthString
このために、サイズの異なる
代入演算子を作成しました。
template<size_t _TOtherSize>
void operator=(const CFixedLengthString<_TOtherSize>&);
そしてもちろん、それをプライベート<20>
にしたので、に変換するとコンパイラエラーが発生し<non-20>
ます。しかし、驚いたことに、コンパイラは文句を言いません!このプライベートオペレーターを呼び出すことができます!
<N>
にコピーされている場合は<N>
、通常の割り当て操作者を呼び出します。<N>
コンパイラにコピー(割り当て)されている場合は、<M>
この特殊な演算子を呼び出します。
しかし、なぜコンパイラはこのシナリオでプライベート(および保護された)の呼び出しを許可するのですか?VC2008コンパイラを使用しています。私はこのコンパイラの解決策だけを探しています。
今のところ、この特殊な関数の本体内に静的アサーションを記述しました(このような誤った変換を禁止するため)。
編集: すべての応答は感謝しています。私の唯一の質問は:
private
なぜ私がエリアに置いた特殊バージョンが呼び出せるのですか?
私たちは皆delete
、防御プログラミングのためにプライベート、宣言のみの関数、属性、およびその他の側面を使用します。私は同じことをしようとしています。しかし、コンパイラはプライベート関数を呼び出すことができます!
編集2: サンプルコード:
template<size_t SIZE>
class FixedString
{
public:
operator const char*();
void operator =(const char*);
void operator =(const FixedString&);
// Disallow
private:
template<size_t OTHERSIZE>
void operator=(const FixedString<OTHERSIZE>&);
};
int main()
{
FixedString<10> buf1;
FixedString<20> buf2;
buf2 = buf1; // NO ERROR!!
}
の特殊バージョンを削除しoperator=
ても、引き続き機能します。そして、私はそれを避けたいです!