template specialization

A

Alexander Stippler

Hi,

what do I have to do to get this (incorrect) piece of code to work. The
specialization is wrong, but how can I do it?

template <typename T, typename V>
class Mask
{
public:
Mask(int i) {}
};

enum DefaultValues
{
ZeroDefault,
NaNDefault,
WhateverDefault
};

template <typename T, typename I, DefaultValues D>
struct DefaultElement
{
static const T value;
};

template <typename T, typename I, DefaultValues D>
const T
DefaultElement<T, I, D>::value = T();

// how to write the following correctly????
template <typename T, typename V>
const T DefaultElement<Mask<T, V>, T, ZeroDefault>::value = Mask<T, V>(1);


Best regards,
alex
 
A

Alexander Stippler

Alexander said:
Hi,

what do I have to do to get this (incorrect) piece of code to work. The
specialization is wrong, but how can I do it?

template <typename T, typename V>
class Mask
{
public:
Mask(int i) {}
};

enum DefaultValues
{
ZeroDefault,
NaNDefault,
WhateverDefault
};

template <typename T, typename I, DefaultValues D>
struct DefaultElement
{
static const T value;
};

template <typename T, typename I, DefaultValues D>
const T
DefaultElement<T, I, D>::value = T();

sorry for the incorrect incorrect code ;-). The type of the const value must
be Mask said:
// how to write the following correctly????
template <typename T, typename V>
const T
DefaultElement<Mask<T, V>, T, ZeroDefault>::value = Mask<T,V>(1);

Thus:

template <typename T, typename V>
const Mask<T, V>
DefaultElement<Mask<T, V>, T, ZeroDefault>::value = Mask<T, V>(1);

But what's wrong with it?
 
J

John Harrison

sorry for the incorrect incorrect code ;-). The type of the const value
must


Thus:

template <typename T, typename V>
const Mask<T, V>
DefaultElement<Mask<T, V>, T, ZeroDefault>::value = Mask<T, V>(1);

But what's wrong with it?

I think you are forgetting to specialise the actual template and just
writing the code for the static value. Try this


template <typename T, typename V>
struct DefaultElement<Mask<T, V>, T, ZeroDefault>
{
static const Mask<T, V> value;
};

template <typename T, typename V>
const Mask<T, V>
DefaultElement<Mask<T, V>, T, ZeroDefault>::value = Mask<T, V>(1);

john
 
V

Victor Bazarov

Alexander said:
Alexander Stippler wrote:




sorry for the incorrect incorrect code ;-). The type of the const value must



Thus:

template <typename T, typename V>
const Mask<T, V>
DefaultElement<Mask<T, V>, T, ZeroDefault>::value = Mask<T, V>(1);

But what's wrong with it?

Wrong? You're trying to _partially_ specialize a member without first
partially specializing the class itself.

Victor
 
A

Alexander Stippler

Victor said:
Alexander Stippler wrote: ...


Wrong? You're trying to _partially_ specialize a member without first
partially specializing the class itself.

Victor


Yes, but how to do it:

template <typename T, typename V>
struct DefaultElement<Mask<T, V>, T, ZeroDefault>
{
static const Mask<T, V> value;
};

This does not solve the problem. Inserting it into the code results in
'template argument list must match the parameter list'.

regards,
Alex
 
J

John Harrison

Yes, but how to do it:

template <typename T, typename V>
struct DefaultElement<Mask<T, V>, T, ZeroDefault>
{
static const Mask<T, V> value;
};

This does not solve the problem. Inserting it into the code results in
'template argument list must match the parameter list'.

regards,
Alex

Then I think you have a broken compiler. That compiles on the two
compilers I tried it on (gcc 3.3.1 and VC++ 7.1).

john
 
A

Alexander Stippler

John said:
Then I think you have a broken compiler. That compiles on the two
compilers I tried it on (gcc 3.3.1 and VC++ 7.1).

john

Yes, now I think so, too. It compiles fine with Intel's icc, but the broken
compiler I tried to use was gcc 3.4 !!!! Seems like a regression!
 
V

Victor Bazarov

John said:
Then I think you have a broken compiler. That compiles on the two
compilers I tried it on (gcc 3.3.1 and VC++ 7.1).

It does? Could you please post your version that compiles? Here is
my attempt:
------------------------------------------------------------
template <typename T, typename V>
class Mask
{
public:
int i;
Mask(int i) {}
};

enum DefaultValues
{
ZeroDefault,
NaNDefault,
WhateverDefault
};

template<typename T, typename I, DefaultValues D>
struct DefaultElement
{
static const T value;
};

template<typename T, typename V>
struct DefaultElement<Mask<T, V>, T, ZeroDefault>
{
static const Mask<T,V> value;
};

int main()
{
DefaultElement<double, char> dedc; // **************
return dedc.value.i;
}
 
V

Victor Bazarov

Victor said:
It does? Could you please post your version that compiles? Here is
my attempt:
------------------------------------------------------------
template <typename T, typename V>
class Mask
{
public:
int i;
Mask(int i) {}
};

enum DefaultValues
{
ZeroDefault,
NaNDefault,
WhateverDefault
};

template<typename T, typename I, DefaultValues D>
struct DefaultElement
{
static const T value;
};

template<typename T, typename V>
struct DefaultElement<Mask<T, V>, T, ZeroDefault>
{
static const Mask<T,V> value;
};

int main()
{
DefaultElement<double, char> dedc; // **************
return dedc.value.i;
}

--------------------------------------------------- This works with VC++
Note that 'DefaultElement' is not specialised based on Mask<T,V> and T,
but instead on T,V, and ZeroDefault.
------------------------------------------------------------------------
template <typename T, typename V>
class Mask
{
public:
int i;
Mask(int i) : i(i) {}
};

enum DefaultValues
{
ZeroDefault,
NaNDefault,
WhateverDefault
};

template<typename T, typename I, DefaultValues D>
struct DefaultElement
{
static const T value;
};

template<typename T, typename V>
struct DefaultElement<T,V,ZeroDefault>
{
static const Mask<T,V> value;
};

template<typename T, typename V>
const Mask<T,V> DefaultElement<T,V,ZeroDefault>::value(42);

int main()
{
DefaultElement<double,char,ZeroDefault> dedc;
return dedc.value.i;
}
 
A

Alexander Stippler

Victor said:
--------------------------------------------------- This works with VC++
Note that 'DefaultElement' is not specialised based on Mask<T,V> and T,
but instead on T,V, and ZeroDefault.
------------------------------------------------------------------------
template <typename T, typename V>
class Mask
{
public:
int i;
Mask(int i) : i(i) {}
};

enum DefaultValues
{
ZeroDefault,
NaNDefault,
WhateverDefault
};

template<typename T, typename I, DefaultValues D>
struct DefaultElement
{
static const T value;
};

template<typename T, typename V>
struct DefaultElement<T,V,ZeroDefault>
{
static const Mask<T,V> value;
};

template<typename T, typename V>
const Mask<T,V> DefaultElement<T,V,ZeroDefault>::value(42);

int main()
{
DefaultElement<double,char,ZeroDefault> dedc;
return dedc.value.i;
}

Are you sure? The general version has template parameter T and defines a
constant of type T. The specialization uses Mask<T,V> as the former T and
ZeroDefault as specialization of D. So if type Mask<T, V> replaced type T
why isn't it
DefaultElement<Mask<T,V>, T, ZeroDefault>
?

Alex
 
A

Alexander Stippler

Victor said:
--------------------------------------------------- This works with VC++
Note that 'DefaultElement' is not specialised based on Mask<T,V> and T,
but instead on T,V, and ZeroDefault.
------------------------------------------------------------------------
template <typename T, typename V>
class Mask
{
public:
int i;
Mask(int i) : i(i) {}
};

enum DefaultValues
{
ZeroDefault,
NaNDefault,
WhateverDefault
};

template<typename T, typename I, DefaultValues D>
struct DefaultElement
{
static const T value;
};

template<typename T, typename V>
struct DefaultElement<T,V,ZeroDefault>
{
static const Mask<T,V> value;
};

template<typename T, typename V>
const Mask<T,V> DefaultElement<T,V,ZeroDefault>::value(42);

int main()
{
DefaultElement<double,char,ZeroDefault> dedc;
return dedc.value.i;
}

Your solution here must be incorrect. It would match any instance with third
argument ZeroDefault, but it only should match if the first argument is
also Mask<T, V> and in no other case.

Alex
 
V

Victor Bazarov

Alexander said:
Victor Bazarov wrote:


I don't think John has verified it properly.

Your solution here must be incorrect. It would match any instance with third
argument ZeroDefault, but it only should match if the first argument is
also Mask<T, V> and in no other case.

Alex, I am not claiming it's "correct". I am simply demonstrating what
code I managed to get to compile on VC++ v7.1, contrary to what John
said in his last post (that it allegedly compiled with gcc and VC++).

Victor
 
V

Victor Bazarov

Alexander said:
[...]

Are you sure? The general version has template parameter T and defines a
constant of type T. The specialization uses Mask<T,V> as the former T and
ZeroDefault as specialization of D. So if type Mask<T, V> replaced type T
why isn't it
DefaultElement<Mask<T,V>, T, ZeroDefault>
?

Alex, I am not trying to solve your problem here. If the first arg
of 'DefaultElement' needs to be Mask<T,V>, let it be. I am simply
showing that the form

template<class T, class V> class DE<Mask<T, V>, T, ZeroDefault>

cannot work. It attempts to specialise on a type that is an argument
of another template. You probably need to declare the first argument
of 'DE' as a _template_ for that.

Victor
 
A

Alexander Stippler

Victor said:
I don't think John has verified it properly.



Alex, I am not claiming it's "correct". I am simply demonstrating what
code I managed to get to compile on VC++ v7.1, contrary to what John
said in his last post (that it allegedly compiled with gcc and VC++).

Victor

Well, John's code compiled well with my gcc3.3.1. With a different choice of
template parameters as you have chosen, i.e.:

DefaultValue<Mask<double, long>, long, ZeroDefault>

Alex
 
V

Victor Bazarov

Alexander said:
Victor Bazarov wrote:

Alexander said:
[...]

Are you sure? The general version has template parameter T and defines a
constant of type T. The specialization uses Mask<T,V> as the former T and
ZeroDefault as specialization of D. So if type Mask<T, V> replaced type T
why isn't it
DefaultElement<Mask<T,V>, T, ZeroDefault>
?

Alex, I am not trying to solve your problem here. If the first arg
of 'DefaultElement' needs to be Mask<T,V>, let it be. I am simply
showing that the form

template<class T, class V> class DE<Mask<T, V>, T, ZeroDefault>

cannot work. It attempts to specialise on a type that is an argument
of another template. You probably need to declare the first argument
of 'DE' as a _template_ for that.

Victor


It cannot work, but it does. Just tried it (finally in a 'real life
example'). Why is it not allowed?

I don't know why all compilers I tried on can't accept them. What exactly
have you done to make it work and on what compiler? Can you post the same
short code like I did?

V
 
A

Alexander Stippler

Victor said:
Alexander said:
[...]

Are you sure? The general version has template parameter T and defines a
constant of type T. The specialization uses Mask<T,V> as the former T and
ZeroDefault as specialization of D. So if type Mask<T, V> replaced type T
why isn't it
DefaultElement<Mask<T,V>, T, ZeroDefault>
?

Alex, I am not trying to solve your problem here. If the first arg
of 'DefaultElement' needs to be Mask<T,V>, let it be. I am simply
showing that the form

template<class T, class V> class DE<Mask<T, V>, T, ZeroDefault>

cannot work. It attempts to specialise on a type that is an argument
of another template. You probably need to declare the first argument
of 'DE' as a _template_ for that.

Victor

It cannot work, but it does. Just tried it (finally in a 'real life
example'). Why is it not allowed?

Alex
 
J

John Harrison

It does? Could you please post your version that compiles? Here is
my attempt:
------------------------------------------------------------
template <typename T, typename V>
class Mask
{
public:
int i;
Mask(int i) {}
};

enum DefaultValues
{
ZeroDefault,
NaNDefault,
WhateverDefault
};

template<typename T, typename I, DefaultValues D>
struct DefaultElement
{
static const T value;
};

template<typename T, typename V>
struct DefaultElement<Mask<T, V>, T, ZeroDefault>
{
static const Mask<T,V> value;
};

int main()
{
DefaultElement<double, char> dedc; // **************
return dedc.value.i;
}
------------------------------------------------------------
VC++ complains at the line marked with ***** saying "too few template
arguments". Have you actually attempted to instantiate DefaultElement?

V

Here

#include <iostream>
using namespace std;

template <typename T, typename V>
class Mask
{
public:
Mask(int i) {}
};

enum DefaultValues
{
ZeroDefault,
NaNDefault,
WhateverDefault
};

template <typename T, typename I, DefaultValues D>
struct DefaultElement
{
static const T value;
};

template <typename T, typename I, DefaultValues D>
const T
DefaultElement<T, I, D>::value = T();

template <typename T, typename V>
struct DefaultElement<Mask<T, V>, T, ZeroDefault>
{
static const Mask<T, V> value;
static const int tester = 1;
};

template <typename T, typename V>
const Mask<T, V>
DefaultElement<Mask<T, V>, T, ZeroDefault>::value = Mask<T, V>(1);

int main()
{
DefaultElement<Mask<int,int>, int, ZeroDefault> x;
std::cout << x.tester << '\n'
return 0;
}

tester has been added to the specialisation to prove that it has been
instantiated. Am I missing the point?

john
 
V

Victor Bazarov

John said:
[...]
tester has been added to the specialisation to prove that it has been
instantiated. Am I missing the point?

No, I was. Sorry to have wasted bandwidth.

I think I was trying to solve a wrong problem. This is what I tried:

template<class T, class U, int i> struct A { enum { original }; };
template<class T, class U> struct B {};
template<class T, class U> struct A<B<T,U>,T,0> { enum { spec }; };

int main() {
return A<B<int,char>,int>::spec;
// ^^^^^^^^^^^^^^^ only 2 arguments
}

it doesn't compile. Why? Because partial specialisations are not
found during lookup. You cannot specify only two arguments. There
needs to be three:

template<class T, class U, int i> struct A { enum { original }; };
template<class T, class U> struct B {};
template<class T, class U> struct A<B<T,U>,T,0> { enum { spec }; };

int main() {
return A<B<int,char>,int,0>::spec;
}

Now it compiles fine.

Victor
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,172
Messages
2,570,934
Members
47,477
Latest member
ColumbusMa

Latest Threads

Top