Visual C++ コンパイラがここで間違ったオーバーロードを呼び出すのはなぜですか?
フォーマット用のバッファを定義するために使用する ostream のサブクラスがあります。一時的なものを作成し、次のような通常の << 演算子を使用してすぐに文字列を挿入したい場合があります。
M2Stream() << "the string";
残念ながら、このプログラムは、operator<<(ostream, const char *) 非メンバー オーバーロードではなく、operator<<(ostream, void *) メンバー オーバーロードを呼び出します。
問題を再現する独自の M2Stream クラスを定義するテストとして、以下のサンプルを作成しました。
問題は、 M2Stream() 式が一時的なものを生成し、これにより何らかの形でコンパイラが void * オーバーロードを優先することだと思います。しかし、なぜ?これは、非メンバー オーバーロード const M2Stream & の最初の引数を作成すると、あいまいさが生じるという事実によって裏付けられています。
もう 1 つの奇妙な点は、次のように、リテラル char 文字列の代わりに、最初に const char * 型の変数を定義してから呼び出すと、目的の const char * オーバーロードが呼び出されることです。
const char *s = "char string variable";
M2Stream() << s;
リテラル文字列が const char * 変数とは異なる型を持っているかのようです! それらは同じであるべきではありませんか?また、一時文字列とリテラル char 文字列を使用すると、コンパイラが void * オーバーロードを呼び出すのはなぜですか?
#include "stdafx.h"
#include <iostream>
using namespace std;
class M2Stream
{
public:
M2Stream &operator<<(void *vp)
{
cout << "M2Stream bad operator<<(void *) called with " << (const char *) vp << endl;
return *this;
}
};
/* If I make first arg const M2Stream &os, I get
\tests\t_stream_insertion_op\t_stream_insertion_op.cpp(39) : error C2666: 'M2Stream::operator <<' : 2 overloads have similar conversions
\tests\t_stream_insertion_op\t_stream_insertion_op.cpp(13): could be 'M2Stream &M2Stream::operator <<(void *)'
\tests\t_stream_insertion_op\t_stream_insertion_op.cpp(20): or 'const M2Stream &operator <<(const M2Stream &,const char *)'
while trying to match the argument list '(M2Stream, const char [45])'
note: qualification adjustment (const/volatile) may be causing the ambiguity
*/
const M2Stream & operator<<(M2Stream &os, const char *val)
{
cout << "M2Stream good operator<<(const char *) called with " << val << endl;
return os;
}
int main(int argc, char argv[])
{
// This line calls void * overload, outputs: M2Stream bad operator<<(void *) called with literal char string on constructed temporary
M2Stream() << "literal char string on constructed temporary";
const char *s = "char string variable";
// This line calls the const char * overload, and outputs: M2Stream good operator<<(const char *) called with char string variable
M2Stream() << s;
// This line calls the const char * overload, and outputs: M2Stream good operator<<(const char *) called with literal char string on prebuilt object
M2Stream m;
m << "literal char string on prebuilt object";
return 0;
}
出力:
M2Stream bad operator<<(void *) called with literal char string on constructed temporary
M2Stream good operator<<(const char *) called with char string variable
M2Stream good operator<<(const char *) called with literal char string on prebuilt object