Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   nested templates and partial specialization (http://www.velocityreviews.com/forums/t805834-nested-templates-and-partial-specialization.html)

ld 11-11-2011 11:45 PM

nested templates and partial specialization
 
Hereafter is a small code which reports my problem. gcc says

problem.cpp:43: error: invalid use of incomplete type ‘struct E<B<T>,
D>’
problem.cpp:3: error: declaration of ‘struct E<B<T>, D>’

Any hint? Thanks.

ld.

// type declaration
template <typename T, typename I>
struct E; // line 3

// abstract class
struct D {
virtual void doit() const = 0;
};

// partial specialization
template <typename T>
struct E<T, D> {
virtual void doit() const;

explicit E(T = T());
T& e;
};

// simple class
struct A {
void doit() const;
int a;
};

// template class
template <typename T>
struct B {
void doit() const;
T b;
};

// specialization with class, ok
template <>
void
E<A, D>::doit() const
{
e.doit();
}

// specialization with template class, error
template <> template <typename T>
void
E<B<T>, D>::doit() const // line 43
{
e.doit();
}

int main() {
E<A, D> a;
E<B<int>, D> b;
}

ld 11-12-2011 07:41 AM

Re: nested templates and partial specialization
 
If you prefer something running here are the same code with the
missing implementation defined and the faulty member function
specialization disabled unless -DFULLSPEC is provided. It works
because the purpose of the class E is to provide default
implementation of abstract classes using partial template
specialization, which can be more specialized by the final class if it
doesn't fit its needs. The real code is more complex, this is a
minimal example to reproduce the problem. Compiling and running with g+
+

$ g++ -std=c++98 -Wall -W -pedantic -O3 problem.cpp
$ ./a.out
A = 1
B = 2
$ g++ -std=c++98 -Wall -W -O3 problem.cpp -DFULLSPEC
problem.cpp:48: error: invalid use of incomplete type ‘struct E<B<T>,
D>’
problem.cpp:5: error: declaration of ‘struct E<B<T>, D>’

regards, ld

// ----- cut & paste below
#include <iostream>

// type declaration
template <typename T, typename I>
struct E;

// abstract class
struct D {
virtual void doit() const = 0;
};

// partial specialization
template <typename T>
struct E<T, D> : D {
virtual void doit() const { this->e.doit(); }

explicit E(T& e_) : e(e_) {}
T& e;
};

// simple class
struct A {
explicit A() : a(1) {}
void doit() const { std::cout << "A = " << a << std::endl; };
int a;
};

// template class
template <typename T>
struct B {
explicit B() : b(2) {}
void doit() const { std::cout << "B = " << b << std::endl; };
T b;
};

// specialization with class, ok
template <>
void
E<A, D>::doit() const
{
e.doit();
}

// specialization with template class, error
#ifdef FULLSPEC
template <> template <typename T>
void
E<B<T>, D>::doit() const // faulty line
{
e.doit();
}
#endif

int main() {
A a; B<int> b;
E<A, D> aa(a); aa.doit();
E<B<int>, D> bb(b); bb.doit();
}
// -----

Edek 11-12-2011 09:16 AM

Re: nested templates and partial specialization
 
On 11/12/2011 08:41 AM, ld wrote:
> template<> template<typename T>
> void
> E<B<T>, D>::doit() const // faulty line


Your notation is for

template<>
template<class T>
E<int, float>::doit<T>()
(or the other way round, I always forget if the outer
template is for the class or member).

Try

template<class T>
void E<B<T>, D>::doit() const

I didn't try compiling it... but it is supposed
to be a partial specialisation of E. Simpler case:

template <class T>
void fun<T*> () const

.... would match all pointers. You get the idea.

Edek

ld 11-12-2011 11:33 AM

Re: nested templates and partial specialization
 
On Nov 12, 10:16*am, Edek <edek.pienkow...@gmail.com> wrote:
> On 11/12/2011 08:41 AM, ld wrote:
>
> > template<> *template<typename T>
> > void
> > E<B<T>, D>::doit() const // faulty line

>
> Your notation is for
>
> template<>
> template<class T>
> E<int, float>::doit<T>()
> (or the other way round, I always forget if the outer
> template is for the class or member).


The outer is for the class and the inner is for the class member but
in my case the two are for the class. You can remove safely the outer
template<>, it changes nothing to the problem. I remember that few
months ago somebody showed a similar problem and got an answer but I
cannot find it again. The answer was containing a use of template in
an uncommon place.

regards, laurent.

Edek 11-12-2011 12:52 PM

Re: nested templates and partial specialization
 
On 11/12/2011 12:33 PM, ld wrote:
> On Nov 12, 10:16 am, Edek<edek.pienkow...@gmail.com> wrote:
>> On 11/12/2011 08:41 AM, ld wrote:
>>
>>> template<> template<typename T>
>>> void
>>> E<B<T>, D>::doit() const // faulty line

>>
>> Your notation is for
>>
>> template<>
>> template<class T>
>> E<int, float>::doit<T>()
>> (or the other way round, I always forget if the outer
>> template is for the class or member).

>
> The outer is for the class and the inner is for the class member but
> in my case the two are for the class. You can remove safely the outer
> template<>, it changes nothing to the problem. I remember that few
> months ago somebody showed a similar problem and got an answer but I
> cannot find it again. The answer was containing a use of template in
> an uncommon place.


The code posted below works, but you need a second E partial
specialisation explicitly. You would need the original
method specialised for <T,D> if you need direct T too.

I can't really understand why E<Something<some_T>, D> does not
match struct E<T,D> - which would be nice, and I assume which
is what you want.

Edek


// type declaration
template <typename T, typename I>
struct E; // line 3

// abstract class
struct D {
virtual void doit() const = 0;
};

// partial specialization
template <typename T>
struct E<T, D> {
virtual void doit() const;

explicit E(T = T());
T& e;
};

// 2nd partial specialisation
template <template<class> class Obj, class T>
struct E<Obj<T>, D> {
typedef Obj<T> TT;
virtual void doit () const;

explicit E(TT = TT());
TT&e;
};

// simple class
struct A {
void doit() const;
int a;
};

// template class
template <typename T>
struct B {
void doit() const;
T b;
};

// specialization with class, ok
template <>
void
E<A, D>::doit() const
{
e.doit();
}

// specialization with template class, error
template <template<class> class Wrap, class T>
void E<Wrap<T>, D>::doit() const // line 43
{
e.doit();
}

int main() {
E<A, D> a;
E<B<int>, D> b;
}




Edek 11-12-2011 01:02 PM

Re: nested templates and partial specialization
 
On 11/12/2011 12:33 PM, ld wrote:
> On Nov 12, 10:16 am, Edek<edek.pienkow...@gmail.com> wrote:
>> On 11/12/2011 08:41 AM, ld wrote:
>>
>>> template<> template<typename T>
>>> void
>>> E<B<T>, D>::doit() const // faulty line

>>
>> Your notation is for
>>
>> template<>
>> template<class T>
>> E<int, float>::doit<T>()
>> (or the other way round, I always forget if the outer
>> template is for the class or member).

>
> The outer is for the class and the inner is for the class member but
> in my case the two are for the class. You can remove safely the outer
> template<>, it changes nothing to the problem. I remember that few
> months ago somebody showed a similar problem and got an answer but I
> cannot find it again. The answer was containing a use of template in
> an uncommon place.


Heh, it is much simpler: there is a subtle difference between
template<class T>
and
template<typename T>

The second one does not match B<T>, while the first one does. The
code below works too.

Edek

// type declaration
template <typename T, typename I>
struct E; // line 3

// abstract class
struct D {
virtual void doit() const = 0;
};

// partial specialization
template <class T>
struct E<T, D> {
virtual void doit() const;

explicit E(T = T());
T& e;
};

// simple class
struct A {
void doit() const;
int a;
};

// template class
template <typename T>
struct B {
void doit() const;
T b;
};

// specialization with class, ok
template <>
void
E<A, D>::doit() const
{
e.doit();
}

// specialization with template class, error NO ERROR NOW
template <class T>
void E<T, D>::doit() const // line 43
{
e.doit();
}

int main() {
E<A, D> a;
E<B<int>, D> b;
}



ld 11-12-2011 01:03 PM

Re: nested templates and partial specialization
 
On Nov 12, 1:52*pm, Edek <edek.pienkow...@gmail.com> wrote:
> On 11/12/2011 12:33 PM, ld wrote:
>
>
>
>
>
>
>
>
>
> > On Nov 12, 10:16 am, Edek<edek.pienkow...@gmail.com> *wrote:
> >> On 11/12/2011 08:41 AM, ld wrote:

>
> >>> template<> * *template<typename T>
> >>> void
> >>> E<B<T>, D>::doit() const // faulty line

>
> >> Your notation is for

>
> >> template<>
> >> template<class T>
> >> E<int, float>::doit<T>()
> >> (or the other way round, I always forget if the outer
> >> template is for the class or member).

>
> > The outer is for the class and the inner is for the class member but
> > in my case the two are for the class. You can remove safely the outer
> > template<>, it changes nothing to the problem. I remember that few
> > months ago somebody showed a similar problem and got an answer but I
> > cannot find it again. The answer was containing a use of template in
> > an uncommon place.

>
> The code posted below works, but you need a second E partial
> specialisation explicitly. You would need the original
> method specialised for <T,D> if you need direct T too.
>
> I can't really understand why E<Something<some_T>, D> does not
> match struct E<T,D> - which would be nice, and I assume which
> is what you want.


Right. I cannot foresee all the use of E that i provide with default
implementations for I, while T is the user's class, (multi)templated
or not... I came up with your solution to solve the problem for some
specific cases but didn't succeed to generalize it for any T, and it
must be transparent for the users.

regards, laurent.

>
> Edek
>
> // type declaration
> template <typename T, typename I>
> struct E; // line 3
>
> // abstract class
> struct D {
> * *virtual void doit() const = 0;
>
> };
>
> // partial specialization
> template <typename T>
> struct E<T, D> {
> * *virtual void doit() const;
>
> * *explicit E(T = T());
> * *T& e;
>
> };
>
> // 2nd partial specialisation
> template <template<class> class Obj, class T>
> struct E<Obj<T>, D> {
> * *typedef Obj<T> TT;
> * *virtual void doit () const;
>
> * *explicit E(TT = TT());
> * *TT&e;
>
> };
>
> // simple class
> struct A {
> * *void doit() const;
> * *int a;
>
> };
>
> // template class
> template <typename T>
> struct B {
> * *void doit() const;
> * *T b;
>
> };
>
> // specialization with class, ok
> template <>
> void
> E<A, D>::doit() const
> {
> * *e.doit();
>
> }
>
> // specialization with template class, error
> template <template<class> class Wrap, class T>
> void E<Wrap<T>, D>::doit() const // line 43
> {
> * *e.doit();
>
> }
>
> int main() {
> * *E<A, D> a;
> * *E<B<int>, D> b;
>
>
>
>
>
>
>
> }



ld 11-12-2011 01:07 PM

Re: nested templates and partial specialization
 
On Nov 12, 2:02*pm, Edek <edek.pienkow...@gmail.com> wrote:
> On 11/12/2011 12:33 PM, ld wrote:
>
>
>
>
>
>
>
>
>
> > On Nov 12, 10:16 am, Edek<edek.pienkow...@gmail.com> *wrote:
> >> On 11/12/2011 08:41 AM, ld wrote:

>
> >>> template<> * *template<typename T>
> >>> void
> >>> E<B<T>, D>::doit() const // faulty line

>
> >> Your notation is for

>
> >> template<>
> >> template<class T>
> >> E<int, float>::doit<T>()
> >> (or the other way round, I always forget if the outer
> >> template is for the class or member).

>
> > The outer is for the class and the inner is for the class member but
> > in my case the two are for the class. You can remove safely the outer
> > template<>, it changes nothing to the problem. I remember that few
> > months ago somebody showed a similar problem and got an answer but I
> > cannot find it again. The answer was containing a use of template in
> > an uncommon place.

>
> Heh, it is much simpler: there is a subtle difference between
> template<class T>
> and
> template<typename T>
>
> The second one does not match B<T>, while the first one does. The
> code below works too.
>
> Edek
>
> // type declaration
> template <typename T, typename I>
> struct E; // line 3
>
> // abstract class
> struct D {
> * *virtual void doit() const = 0;
>
> };
>
> // partial specialization
> template <class T>
> struct E<T, D> {
> * *virtual void doit() const;
>
> * *explicit E(T = T());
> * *T& e;
>
> };
>
> // simple class
> struct A {
> * *void doit() const;
> * *int a;
>
> };
>
> // template class
> template <typename T>
> struct B {
> * *void doit() const;
> * *T b;
>
> };
>
> // specialization with class, ok
> template <>
> void
> E<A, D>::doit() const
> {
> * *e.doit();
>
> }
>
> // specialization with template class, error NO ERROR NOW
> template <class T>
> void E<T, D>::doit() const // line 43


But it is not anymore a specialization for B<T> but just T, that is
why it works. Assume that another class C<T> wants to specialize it
too. How does it make the difference? Moreover, in this case, typename
and class have the same meaning (not always the case though).

regards, laurent.

> {
> * *e.doit();
>
> }
>
> int main() {
> * *E<A, D> a;
> * *E<B<int>, D> b;
>
>
>
>
>
>
>
> }



Edek 11-12-2011 03:18 PM

Re: nested templates and partial specialization
 
On 11/12/2011 02:07 PM, ld wrote:
> But it is not anymore a specialization for B<T> but just T, that is
> why it works. Assume that another class C<T> wants to specialize it
> too. How does it make the difference? Moreover, in this case, typename
> and class have the same meaning (not always the case though).


Yes, right, sorry.

Actually I think you are trying a member specialisation by a weird
specialisation of the class (just the method, not whole class). It
works with sfinae, but not for virtual methods, and I am not sure
about partial class specialisations.

The below uses inheritance to get the example working - I don't know
if this fits your usage, but inheritance is one way of doing such
things.

Edek

// type declaration
template <typename T, typename I>
struct E; // line 3

// abstract class
struct D {
virtual void doit() const = 0;
};

template <class T, class TT> struct helper {
void doitInternal (T const&) const;
};


// partial specialization
template <class T>
struct E<T, D> : public helper<T,D> {
virtual void doit() const;

explicit E(T = T());
T& e;
};



// simple class
struct A {
void doit() const;
int a;
};

// template class
template <typename T>
struct B {
void doit() const;
T b;
};

// specialization with class, ok
template <>
void E<A, D>::doit() const
{
e.doit();
}

template <class T>
struct helper<B<T>, D> {
void doitInternal (B<T> const&) const;
};

template <class T>
void E<T, D>::doit() const
{
doitInternal(e);
}

template <class T, class TT>
void helper<T,TT>::doitInternal(T const&) const {}

template <class T>
void helper<B<T>, D>::doitInternal(B<T> const& e) const // line 43
{
// for B<T>
e.doit();
}



int main() {
E<A, D> a;
E<B<int>, D> b;
}



All times are GMT. The time now is 07:52 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.