Hi All,
I have this example that attempts to call a member template
constructor
whilst explicitly specifying the template parameters. I realize that
by using
static_cast one can force the parameters to the right type (via
argument
deduction), but for normal member templates one [can] explicitly
specify
the template parameters. I would think there would be consistency
here.
Example:
struct X
{
template <class T>
X( T* p );
template <class T>
X foo( T* p );
};
struct Base{};
struct Derived : Base{};
void foo( const X& );
int main()
{
Derived d;
//X x<Base>( &d ); //Does not compile!!!!
X x( static_cast<Base*>(&d) );
foo( x.foo( &d ) );
foo( x.foo<Base>( &d ) ); //Does compile!!!
}
Any comments as to why this is so appreciated, Thanks.
Werner
|
|
0
|
|
|
|
Reply
|
werasm
|
3/24/2010 9:17:16 AM |
|
On 24 mar, 10:17, werasm <wer...@gmail.com> wrote:
> Hi All,
>
> I have this example that attempts to call a member template
> constructor
> whilst explicitly specifying the template parameters. I realize that
> by using
> static_cast one can force the parameters to the right type (via
> argument
> deduction), but for normal member templates one [can] explicitly
> specify
> the template parameters. I would think there would be consistency
> here.
>
> Example:
>
> struct X
> {
> =A0 template <class T>
> =A0 X( T* p );
> =A0 template <class T>
> =A0 X foo( T* p );
>
> };
>
> struct Base{};
> struct Derived : Base{};
>
> void foo( const X& );
>
> int main()
> {
> =A0 Derived d;
> =A0 //X x<Base>( &d ); //Does not compile!!!!
> =A0 X x( static_cast<Base*>(&d) );
>
> =A0 foo( x.foo( &d ) );
> =A0 foo( x.foo<Base>( &d ) ); //Does compile!!!
>
> }
>
> Any comments as to why this is so appreciated, Thanks.
Because constructors do not have names.
As for your problem, it is easily solved by using a (1) construction
function or (2) passing an additional parameter.
(1)
struct X
{
template <class T>
static X make( T* p );
template <class T>
X foo( T* p );
};
X x =3D X::make<Base>(&d);
(2)
template<class T>
struct ForceType { };
struct X
{
template <class T, class F >
X( T* p , const ForceType<F>& force_type =3D ForceType<T>() )
{
F* pf =3D p;//...
}
};
X x(&d,ForceType<Base>());
--
Michael
|
|
0
|
|
|
|
Reply
|
Michael
|
3/24/2010 9:54:40 AM
|
|
On Mar 24, 11:54=A0am, Michael Doubez <michael.dou...@free.fr> wrote:
> Because constructors do not have names.
Yes, I realize that there must be a way to discern between member
templates and the class template (the name used for the class
template). I was wondering if there is
perhaps a way
e.g: X.template x<Base>( &d );
// Calls member template constructor, instantiating
// x of type X...
I can accept that the use for something to this effect will be rare.
I've
decided on simply using static cast:
X x( static_cast<Base>( Derived*(0) );
Kind regards,
Werner
|
|
0
|
|
|
|
Reply
|
werasm
|
3/24/2010 10:26:21 AM
|
|
On 24 Mrz., 10:54, Michael Doubez wrote:
> (2)
> template<class T>
> struct ForceType { };
>
> struct X
> {
> =A0 template <class T, class F >
> =A0 X( T* p , const ForceType<F>& force_type =3D ForceType<T>() )
> =A0 {
> =A0 =A0 F* pf =3D p;//...
> =A0 }
> };
>
> X x(&d,ForceType<Base>());
The default parameter doesn't work here. At least G++ is rejecting it
and I think this is because F cannot be deduced by the default
parameter. Since you need to supply some dummy ForceType<>-Object so
that F can be deduced you could reduce the number of template
parameters and instantiations via
template<class T>struct identity{typedef T type;};
struct X
{
template <class T>
X(identity<T>, typename identity<T>::type* p);
// ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
// (1) (2)
//
// 1: type tag, used for template argument deduction
// 2: prevents template argument deduction for the
// second parameter
};
:
derived d;
X x(identity<base>(),&d); // 3
This has also the benefit of the implicit pointer conversion being
outside of the constructor. In case this conversion is ill-formed the
compiler will point you to the offending line (3) instead of pointing
you to the constructor of X.
But I honestly see no advantage over
struct X
{
template <class T>
X(T*);
};
X x(static_cast<base*>(&d));
Cheers,
SG
|
|
0
|
|
|
|
Reply
|
SG
|
3/24/2010 10:48:08 AM
|
|
On Mar 24, 2:17=A0am, werasm <wer...@gmail.com> wrote:
> Hi All,
>
> I have this example that attempts to call a member template
> constructor
> whilst explicitly specifying the template parameters. I realize that
> by using
> static_cast one can force the parameters to the right type (via
> argument
> deduction), but for normal member templates one [can] explicitly
> specify
> the template parameters. I would think there would be consistency
> here.
>
> Example:
>
> struct X
> {
> =A0 template <class T>
> =A0 X( T* p );
> =A0 template <class T>
> =A0 X foo( T* p );
>
> };
>
> struct Base{};
> struct Derived : Base{};
>
> void foo( const X& );
>
> int main()
> {
> =A0 Derived d;
> =A0 //X x<Base>( &d ); //Does not compile!!!!
Shouldn't this line be X<Base> x(&d) ???
|
|
0
|
|
|
|
Reply
|
red
|
3/24/2010 5:02:55 PM
|
|
On Mar 24, 2:17=A0am, werasm <wer...@gmail.com> wrote:
> Hi All,
>
> I have this example that attempts to call a member template
> constructor
> whilst explicitly specifying the template parameters. I realize that
> by using
> static_cast one can force the parameters to the right type (via
> argument
> deduction), but for normal member templates one [can] explicitly
> specify
> the template parameters. I would think there would be consistency
> here.
>
> Example:
>
> struct X
> {
> =A0 template <class T>
> =A0 X( T* p );
> =A0 template <class T>
> =A0 X foo( T* p );
>
> };
>
> struct Base{};
> struct Derived : Base{};
>
> void foo( const X& );
>
> int main()
> {
> =A0 Derived d;
> =A0 //X x<Base>( &d ); //Does not compile!!!!
Shouldn't this line be X<Base> x(&d) ???
|
|
0
|
|
|
|
Reply
|
red
|
3/24/2010 5:03:06 PM
|
|
On 24 mar, 11:48, SG <s.gesem...@gmail.com> wrote:
> On 24 Mrz., 10:54, Michael Doubez wrote:
>
> > (2)
> > =A0 template<class T>
> > =A0 struct ForceType { };
>
> > =A0 struct X
> > =A0 {
> > =A0 =A0 template <class T, class F >
> > =A0 =A0 X( T* p , const ForceType<F>& force_type =3D ForceType<T>() )
> > =A0 =A0 {
> > =A0 =A0 =A0 F* pf =3D p;//...
> > =A0 =A0 }
> > =A0 };
>
> > =A0 X x(&d,ForceType<Base>());
>
> The default parameter doesn't work here. At least G++ is rejecting it
> and I think this is because F cannot be deduced by the default
> parameter.
Yes.
=A714.8.2/17: a template type-parameter cannot be deduced from the type
of a function default argument.
[snip]
> But I honestly see no advantage over
>
> =A0 =A0struct X
> =A0 =A0{
> =A0 =A0 =A0template <class T>
> =A0 =A0 =A0X(T*);
> =A0 =A0};
>
> =A0 =A0X x(static_cast<base*>(&d));
From the very beginning the question is biased: if you have a template
argument, I don't the reason why you would want to instantiate it with
a base class.
Unless the member function became protected in the derived but then
the cast should obviously be explicit.
--
Michael
|
|
0
|
|
|
|
Reply
|
Michael
|
3/25/2010 8:47:45 AM
|
|
On Mar 25, 10:47=A0am, Michael Doubez <michael.dou...@free.fr> wrote:
> On 24 mar, 11:48, SG <s.gesem...@gmail.com> wrote:
>
>
>
> > On 24 Mrz., 10:54, Michael Doubez wrote:
>
> > > (2)
> > > =A0 template<class T>
> > > =A0 struct ForceType { };
>
> > > =A0 struct X
> > > =A0 {
> > > =A0 =A0 template <class T, class F >
> > > =A0 =A0 X( T* p , const ForceType<F>& force_type =3D ForceType<T>() )
> > > =A0 =A0 {
> > > =A0 =A0 =A0 F* pf =3D p;//...
> > > =A0 =A0 }
> > > =A0 };
>
> > > =A0 X x(&d,ForceType<Base>());
>
> > The default parameter doesn't work here. At least G++ is rejecting it
> > and I think this is because F cannot be deduced by the default
> > parameter.
>
> Yes.
> =A714.8.2/17: a template type-parameter cannot be deduced from the type
> of a function default argument.
>
> [snip]
>
> > But I honestly see no advantage over
>
> > =A0 =A0struct X
> > =A0 =A0{
> > =A0 =A0 =A0template <class T>
> > =A0 =A0 =A0X(T*);
> > =A0 =A0};
>
> > =A0 =A0X x(static_cast<base*>(&d));
>
> From the very beginning the question is biased: if you have a template
> argument, I don't the reason why you would want to instantiate it with
> a base class.
> Unless the member function became protected in the derived but then
> the cast should obviously be explicit.
>
> --
> Michael
Because boost::any when casting back (see its implementation) requires
the exact type, not the polymorphic type....
|
|
0
|
|
|
|
Reply
|
werasm
|
3/25/2010 10:35:46 AM
|
|
|
7 Replies
325 Views
(page loaded in 0.056 seconds)
|