# Template problem

This topic is 4439 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

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:
#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);
}
};


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:
(*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);
}
};


Now, I tried testing it like this:
int main()
{
A* a = new B;

(*a) << std::setw(5);

return 0;
}


But I get the error:
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
]


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:
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.

##### Share on other sites
I have found a solution to my problem. Instead of having a function where the type have to be known when it is called, I have moved the template code inside the class which know which type it is. So instead of all the setw stuff at start I have created a class like this:
class setw{	std::streamsize _Param;public:	setw(std::streamsize pParam)		:		_Param( pParam )	{		}	~setw()	{		}	template<typename T>	void Execute(T& pTarget)	{		pTarget.setw( _Param );	}	};

Then the A::operator<< recieves a setw object and calls Execute<A>.

##### Share on other sites
Yeah that's the kind of thing I've done in similiar circumstances. It's not easy programming a lot of the stuff we take for granted is it!

• 10
• 11
• 11
• 11
• 9