Article ID: 148686 - Last Review: December 2, 2003 - Revision: 2.0
FIX: IOMANIPdeclare Macro Causes C2758 Error with References This article was previously published under Q148686
When a IOMANIPdeclare() macro is used with a reference type, the compiler
generates the following error message:
error C2758: '_tp' : must be initialized in constructor base/member
initializer list
The IOMANIPdeclare() macro is expanded into a number of classes containing
data members of the type passed into the IOMANIPdeclare() macro. The
constructors for these classes are written such that the data members are
initialized in the body of each class constructor. This is not allowed for
reference type data members. Reference type data members should be
initialized in a member initialization list for the class constructor.
Modify the IOMANIPdeclare() macro (defined in Iomanip.h) so that the
class data members are initialized in a member initialization list
instead of in the body of the constructor.
For example, the following line is defined in the IOMANIPdeclare() macro
definition:
SMANIP(T)(ios& (*f)(ios&,T), T t) { _fp = f; _tp = t; }
The inline constructor body where the class data members are initialized
can be modifed so that the constructor uses a member initialization list
as follows:
SMANIP(T)(ios& (*f)(ios&,T), T t) : _fp(f), _tp(t) {}
This change must be made for each class constructor that initializes the
_fp and _tp data members. These declarations are:
SMANIP(T)(ios& (*f)(ios&,T), T t) { _fp = f; _tp = t; }
IMANIP(T)(istream& (*f)(istream&,T), T t) { _fp = f; _tp = t; }
OMANIP(T)(ostream& (*f)(ostream&,T), T t) { _fp = f; _tp = t; }
IOMANIP(T)(iostream& (*f)(iostream&,T), T t) { _fp = f; _tp = t; }
After making this change, you can use reference data types in the
IOMANIPdeclare() macro.
Microsoft has confirmed this to be a bug in the Microsoft products listed
at the beginning of this article.
This problem was corrected in Microsoft Visual C++ .NET.
Sample Code
/*
The following sample code demonstrates both the error, and the
workaround.
Compile options needed: none
/DWORKAROUND to enable the workaround macro
*/
#include <iostream.h>
#include <iomanip.h>
// --------------------------------------------------------
// following is the workaround macro
#ifdef WORKAROUND
#ifdef IOMANIPdeclare
#undef IOMANIPdeclare
#define IOMANIPdeclare(T) \
class SMANIP(T) { \
public: \
SMANIP(T)(ios& (*f)(ios&,T), T t) : _tp(t), _fp(f) {} \
friend istream& operator>>(istream& s, const SMANIP(T) & sm) { \
(*(sm._fp))(s,sm._tp); return s; \
} \
friend ostream& operator<<(ostream& s, const SMANIP(T) & sm) { \
(*(sm._fp))(s,sm._tp); return s; \
} \
private: \
ios& (* _fp)(ios&,T); \
T _tp; \
}; \
class SAPP(T) { \
public: \
SAPP(T)( ios& (*f)(ios&,T)) { _fp = f; } \
SMANIP(T) operator()(T t) { return SMANIP(T)(_fp,t); } \
private: \
ios& (* _fp)(ios&,T); \
}; \
class IMANIP(T) { \
public: \
IMANIP(T)(istream& (*f)(istream&,T), T t) : _tp(t), _fp(f) {} \
friend istream& operator>>(istream& s, IMANIP(T) & sm) { \
(*sm._fp)(s,sm._tp); return s; \
} \
private: \
istream& (* _fp)(istream&,T); \
T _tp; \
}; \
class IAPP(T) { \
public: \
IAPP(T)( istream& (*f)(istream&,T)) { _fp = f; } \
IMANIP(T) operator()(T t) { return IMANIP(T)(_fp,t); } \
private: \
istream& (* _fp)(istream&,T); \
}; \
class OMANIP(T) { \
public: \
OMANIP(T)(ostream& (*f)(ostream&,T), T t) : _tp(t), _fp(f) {} \
friend ostream& operator<<(ostream& s, OMANIP(T) & sm) { \
(*sm._fp)(s,sm._tp); return s; \
} \
private: \
ostream& (* _fp)(ostream&,T); \
T _tp; \
}; \
class OAPP(T) { \
public: \
OAPP(T)(ostream& (*f)(ostream&,T)) { _fp = f; } \
OMANIP(T) operator()(T t) { return OMANIP(T)(_fp,t); } \
private: \
ostream& (* _fp)(ostream&,T); \
}; \
class IOMANIP(T) { \
public: \
IOMANIP(T)(iostream& (*f)(iostream&,T), T t) : _tp(t), _fp(f) {} \
friend istream& operator>>(iostream& s, IOMANIP(T) & sm) { \
(*sm._fp)(s,sm._tp); return s; \
} \
friend ostream& operator<<(iostream& s, IOMANIP(T) & sm) { \
(*sm._fp)(s,sm._tp); return s; \
} \
private: \
iostream& (* _fp)(iostream&,T); T _tp; \
}; \
class IOAPP(T) { \
public: \
IOAPP(T)( iostream& (*f)(iostream&,T)) { _fp = f; } \
IOMANIP(T) operator()(T t) { return IOMANIP(T)(_fp,t); } \
private: \
iostream& (* _fp)(iostream&,T); \
};
#endif //IOMANIPdeclare
#endif //WORKAROUND
// This is the end of the workaround macro
// --------------------------------------------------------
typedef int& fillpair;
IOMANIPdeclare( fillpair );
ostream& fp( ostream& os, fillpair pair ) {
for ( int c = 0; c < 10; c++ ) {
os << pair;
}
return os;
}
OMANIP(fillpair) fill( fillpair var ) {
return OMANIP(fillpair)( fp, var);
}
void main() {
int test=0;
fillpair var=test;
cout << "10 things coming " << fill( var ) << " done " << endl;
}
// ***** End of code sample ******
APPLIES TO Microsoft Visual C++ 1.52 Professional Edition Microsoft Visual C++ 2.2 Microsoft Visual C++ 4.0 Standard Edition Microsoft Visual C++ 4.1 Subscription Microsoft Visual C++ 4.2 Enterprise Edition Microsoft Visual C++ 5.0 Enterprise Edition Microsoft Visual C++ 6.0 Enterprise Edition Microsoft Visual C++ 4.2 Professional Edition Microsoft Visual C++ 5.0 Professional Edition Microsoft Visual C++ 6.0 Professional Edition Microsoft Visual C++, 32-bit Learning Edition 6.0 kbbug kbfix kbnoupdate kbcpponly kbcompiler kbarttypeinf KB148686
Provide feedback on this information
Did this information solve your problem?
Was this information relevant?
What can we do to improve this information?
To protect your privacy, do not include contact information in your feedback.
Thank you! Your feedback is used to help us improve our support content. For more assistance options, please visit the
Help and Support Home Page .