Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #11407 > unrolled thread
| Started by | ld <laurent.deniau@gmail.com> |
|---|---|
| First post | 2011-11-11 15:45 -0800 |
| Last post | 2011-11-12 16:18 +0100 |
| Articles | 9 — 2 participants |
Back to article view | Back to comp.lang.c++
nested templates and partial specialization ld <laurent.deniau@gmail.com> - 2011-11-11 15:45 -0800
Re: nested templates and partial specialization ld <laurent.deniau@gmail.com> - 2011-11-11 23:41 -0800
Re: nested templates and partial specialization Edek <edek.pienkowski@gmail.com> - 2011-11-12 10:16 +0100
Re: nested templates and partial specialization ld <laurent.deniau@gmail.com> - 2011-11-12 03:33 -0800
Re: nested templates and partial specialization Edek <edek.pienkowski@gmail.com> - 2011-11-12 13:52 +0100
Re: nested templates and partial specialization ld <laurent.deniau@gmail.com> - 2011-11-12 05:03 -0800
Re: nested templates and partial specialization Edek <edek.pienkowski@gmail.com> - 2011-11-12 14:02 +0100
Re: nested templates and partial specialization ld <laurent.deniau@gmail.com> - 2011-11-12 05:07 -0800
Re: nested templates and partial specialization Edek <edek.pienkowski@gmail.com> - 2011-11-12 16:18 +0100
| From | ld <laurent.deniau@gmail.com> |
|---|---|
| Date | 2011-11-11 15:45 -0800 |
| Subject | nested templates and partial specialization |
| Message-ID | <d4241487-2730-422c-81b4-e23ead8fcc9b@t8g2000yql.googlegroups.com> |
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;
}
[toc] | [next] | [standalone]
| From | ld <laurent.deniau@gmail.com> |
|---|---|
| Date | 2011-11-11 23:41 -0800 |
| Message-ID | <8ff5cd3a-72b4-46c9-8d97-23b7ed9b9d82@k10g2000yqn.googlegroups.com> |
| In reply to | #11407 |
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();
}
// -----
[toc] | [prev] | [next] | [standalone]
| From | Edek <edek.pienkowski@gmail.com> |
|---|---|
| Date | 2011-11-12 10:16 +0100 |
| Message-ID | <j9ldee$5pq$1@node2.news.atman.pl> |
| In reply to | #11411 |
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
[toc] | [prev] | [next] | [standalone]
| From | ld <laurent.deniau@gmail.com> |
|---|---|
| Date | 2011-11-12 03:33 -0800 |
| Message-ID | <8749ba8c-95da-46f8-a9c0-a9e44a143158@cu3g2000vbb.googlegroups.com> |
| In reply to | #11414 |
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.
[toc] | [prev] | [next] | [standalone]
| From | Edek <edek.pienkowski@gmail.com> |
|---|---|
| Date | 2011-11-12 13:52 +0100 |
| Message-ID | <j9lq3k$j5n$1@node2.news.atman.pl> |
| In reply to | #11415 |
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;
}
[toc] | [prev] | [next] | [standalone]
| From | ld <laurent.deniau@gmail.com> |
|---|---|
| Date | 2011-11-12 05:03 -0800 |
| Message-ID | <2156a2bb-6266-4d8d-afd7-630573b10a6a@l24g2000yqm.googlegroups.com> |
| In reply to | #11416 |
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;
>
>
>
>
>
>
>
> }
[toc] | [prev] | [next] | [standalone]
| From | Edek <edek.pienkowski@gmail.com> |
|---|---|
| Date | 2011-11-12 14:02 +0100 |
| Message-ID | <j9lqmq$jnb$1@node2.news.atman.pl> |
| In reply to | #11415 |
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;
}
[toc] | [prev] | [next] | [standalone]
| From | ld <laurent.deniau@gmail.com> |
|---|---|
| Date | 2011-11-12 05:07 -0800 |
| Message-ID | <1d599554-4659-4b13-9ade-077a2c67cddf@s5g2000vbe.googlegroups.com> |
| In reply to | #11417 |
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;
>
>
>
>
>
>
>
> }
[toc] | [prev] | [next] | [standalone]
| From | Edek <edek.pienkowski@gmail.com> |
|---|---|
| Date | 2011-11-12 16:18 +0100 |
| Message-ID | <j9m2lp$rlu$1@node2.news.atman.pl> |
| In reply to | #11419 |
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;
}
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c++
csiph-web