#include <iostream>
struct fubar
{
fubar()
{
std::cout << "("
<< this
<< ")->fubar::fubar()"
<< std::endl;
}
~fubar()
{
std::cout << "("
<< this
<< ")->fubar::~fubar()"
<< std::endl;
}
void display()
{
std::cout << "("
<< this
<< ")->fubar::display()"
<< std::endl;
}
};
struct foo
{
fubar& m_fubar;
foo(fubar& fubar_, int x)
: m_fubar(fubar_)
{
std::cout << "("
<< this
<< ")->foo::foo()"
<< std::endl;
}
~foo()
{
std::cout << "("
<< this
<< ")->foo::~foo()"
<< std::endl;
}
void display_fubar()
{
m_fubar.display();
}
};
template<typename T>
struct wrapper : public T
{
template<typename P1>
wrapper(P1& p1)
: T(p1)
{
}
template<typename P1>
wrapper(P1 const& p1)
: T(p1)
{
}
template<typename P1, typename P2>
wrapper(P1& p1, P2& p2)
: T(p1, p2)
{
}
template<typename P1, typename P2>
wrapper(P1 const& p1, P2& p2)
: T(p1, p2)
{
}
template<typename P1, typename P2>
wrapper(P1& p1, P2 const& p2)
: T(p1, p2)
{
}
template<typename P1, typename P2>
wrapper(P1 const& p1, P2 const& p2)
: T(p1, p2)
{
}
};
int
main()
{
{
fubar fb;
wrapper<foo> f(fb, 5);
f.display_fubar();
}
return 0;
}
Notice all of the constructor overloads in the wrapper template... Are those
even legal? Can they get me into trouble? Will there be any ambiguity
problems?
One problem I can see... The number of overloads can get very high when the
number of parameters increases. I guess I can create a little program to
automatically generate all of them. Would that even be feasible?
Thanks!
As far as I know you can overload whatever you want, as long as you do
not have exactly the same argument list twice. I.e. two overloaded
functions must not differ in the return type only.
> Can they get me into trouble?
However, sometimes it might be quite difficult to avoid ambiguities when
calling the overloaded method.
> Will there be any
> ambiguity problems?
Not in your example.
But change your code to
int
main()
{
{
volatile fubar fb;
wrapper<foo> f(fb, 5);
f.display_fubar();
}
return 0;
}
and this will change.
> One problem I can see... The number of overloads can get very high when
> the number of parameters increases.
Well variadic templates would be nice. If you have the option C++0x,
there is a straight forward solution for any number of arguments.
template<typename T>
struct wrapper : public T
{
template<typename... P1>
wrapper(P1... p1)
: T(p1...)
{
}
};
> I guess I can create a little
> program to automatically generate all of them. Would that even be feasible?
Feel free to do so, but I see no need for all of these methods. Do you
want to enforce reference parameters? If not
template<typename T>
struct wrapper : public T
{
template<typename P1>
wrapper(P1 p1)
: T(p1)
{
}
template<typename P1, typename P2>
wrapper(P1 p1, P2 p2)
: T(p1, p2)
{
}
};
will do the Job as well without any risk of ambiguity.
Marcel
Okay. Well, it does work when I add the proper overload and modify foo and
fubar accordingly:
template<typename P1, typename P2>
wrapper(P1 volatile& p1, P2 const& p2)
: T(p1, p2)
{
}
>> One problem I can see... The number of overloads can get very high when
>> the number of parameters increases.
>
> Well variadic templates would be nice. If you have the option C++0x, there
> is a straight forward solution for any number of arguments.
>
> template<typename T>
> struct wrapper : public T
> {
> template<typename... P1>
> wrapper(P1... p1)
> : T(p1...)
> {
>
> }
> };
Oh that would be great! However, I don't have that option.
DAMN!
>> I guess I can create a little program to automatically generate all of
>> them. Would that even be feasible?
>
>
> Feel free to do so, but I see no need for all of these methods. Do you
> want to enforce reference parameters? If not
>
> template<typename T>
> struct wrapper : public T
> {
> template<typename P1>
> wrapper(P1 p1)
> : T(p1)
> {
>
> }
>
> template<typename P1, typename P2>
> wrapper(P1 p1, P2 p2)
> : T(p1, p2)
> {
>
> }
> };
>
> will do the Job as well without any risk of ambiguity.
Can I force reference parameters by doing something like:
#include <iostream>
struct foo
{
fubar& m_fubar;
void display_fubar()
{
m_fubar.display();
}
};
template<typename T>
struct wrapper : public T
{
template<typename P1, typename P2>
wrapper(P1 p1, P2 p2)
: T(p1, p2)
{
}
};
template<typename T>
class reference
{
T const& m_reference;
public:
reference(T const& ref)
: m_reference(ref)
{
}
operator T const& () const
{
return m_reference;
}
operator T& ()
{
return *const_cast<T*>(&m_reference);
}
};
template<typename T>
static reference<T>
create_ref(T const& ref)
{
return reference<T>(ref);
}
int
main()
{
{
fubar fb;
wrapper<foo> f(create_ref(fb), 5);
f.display_fubar();
}
return 0;
}
?