Причина, по которой операторы ostream
возвращают ссылку на ostream
, и причина, по которой это несколько помогло вашему случаю вернуть ссылку на MyClass
, заключается в том, что выражение типа A << B << C
всегда интерпретируется как (A << B) << C
. То есть все, что возвращает первый перегруженный оператор, становится левой частью следующего вызова оператора.
Теперь, если вы хотите, чтобы выражение типа MyInstance << "First text" << 1 << 2
вызывало ошибку компилятора, вам нужно убедиться, что тип, возвращаемый после первых двух операторов <<
, является типом, который нельзя вызвать с другим int. Я думаю, что-то подобное может сделать то, что вы хотите (спасибо @Pete Kirkham за хорошую идею по улучшению):
struct MyClass_ExpectInt;
class MyClass {
private:
friend MyClass& operator<<(const MyClass_ExpectInt&, int);
void insert_data(const std::string& StringData, int IntData);
// ...
};
struct MyClass_ExpectInt {
MyClass& obj_ref;
std::string str_data;
explicit MyClass_ExpectInt( MyClass& obj, const std::string& str )
: obj_ref( obj ), str_data( str ) {}
};
MyClass_ExpectInt operator<<( MyClass& obj, const std::string& StringData )
{
// Do nothing until we have both a string and an int...
return MyClass_ExpectInt( obj, StringData );
}
MyClass& operator<<( const MyClass_ExpectInt& helper, int IntData )
{
helper.obj_ref.insert_data( helper.str_data, IntData );
return helper.obj_ref;
}
Это будут только две перегруженные функции operator<<
, которые вы определяете, связанные с MyClass
. Таким образом, каждый раз, когда вы вызываете operator<<
, компилятор переключает тип возвращаемого значения с MyClass&
на MyClass_ExpectInt
или наоборот, и передача «неправильных» данных в operator<<
никогда не допускается.