Original Post
I have tried re-creating the streaming interface many classes in the SC++L have (like std::cout, std::ofstream etc.). I have got stuff like std::endl, std::left, std::showboolalpha etc. to work, but I still need to implement functionality for the "stuff" (what is these called? I heard the term manipulators used once, but I'm not sure if that is correct) with parameters, like std::setw. I have tried implementing the functionality, but have some problems. I have created this base interface: This might be a little complicated. Everything in Hid shouldn't be accessed from the user's code. The idea is that the user will do something like this: Now, I tried testing it like this: But I get the error: The std::_Smanip is VC 8.0's ManipulatorWParam equivilant. It holds the function pointer and the argument value. The "A &A::operator <<(std::pair<_Ty1,_Ty2>)'" is the:
#include <iostream>
#include <iomanip>
namespace Hid //Hidden/Internal stuff
{
template<typename T, typename TParam>
struct ManipulatorWParam
{
typedef void (*Func)(T& pTarget,TParam pParam);
typedef std::pair<Func,TParam> Complete;
};
template<typename T>
void setw (T& pTarget,std::streamsize pSize)
{
pTarget.setw (pSize);
}
}
namespace std
{
template<typename T>
typename Hid::ManipulatorWParam<T,std::streamsize>::Complete setw (std::streamsize pParam)
{
return Hid::ManipulatorWParam<T,std::streamsize>::Complete(Hid::setw,pParam);
}
}
class A
{
public:
virtual void setw(std::streamsize pSize) = 0;
A& operator<<(Hid::ManipulatorWParam<A,std::streamsize>::Complete pManipulator)
{
pManipulator.first(*this,pManipulator.second);
return (*this);
}
};
(*a) << std::setw(5);
std::setw(5) will then return:
Hid::ManipulatorWParam<T,std::streamsize>::Complete(Hid::setw,5);
The << operator should then get this std::pair with a function pointer and the parameter to pass to the function pointer. The function pointer will then call A::setw with the parameter. The setw function in A is pure virtual because only classes derived from A will know what to do when setw is called, in most cases they will have an internal stream they will call. I tried creating a simple example using std::cout, like this:
class B : public A
{
public:
void setw(std::streamsize pSize)
{
std::cout << std::setw(pSize);
}
};
int main()
{
A* a = new B;
(*a) << std::setw(5);
return 0;
}
e:\code\test\main.cpp(51) : error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'std::_Smanip<_Arg>' (or there is no acceptable conversion)
with
[
_Arg=std::ios_base::fmtflags
]
e:\code\test\main.cpp(31): could be 'A &A::operator <<(std::pair<_Ty1,_Ty2>)'
with
[
_Ty1=void (__cdecl *)(A &,std::streamsize),
_Ty2=std::streamsize
]
while trying to match the argument list '(A, std::_Smanip<_Arg>)'
with
[
_Arg=std::ios_base::fmtflags
]
A& operator<<(Hid::ManipulatorWParam<A,std::streamsize>::Complete pManipulator)
Operator, but as you might remember Complete was just a typedef for a std::pair. So I think the compiler for some reason think the SC++L's std::setw is more appropriate. I have tried moving std::setw to another namespace, then I just get (moved to m1a namespace):
e:\code\test\main.cpp(51) : error C2783: 'Hid::ManipulatorWParam<T,std::streamsize>::Complete m1a::setw(std::streamsize)' : could not deduce template argument for 'T'
e:\code\test\main.cpp(21) : see declaration of 'm1a::setw'
So it can't figure out the template argument, T. I tried explicitely specifiying T as A and then the code compiles fine, but I'ld like to not manually specify the type. I hope someone can help me to fix my code.