partial template specialization

C

cpunerd

I'm confused as to the syntax for partial template specialization.
Below is a very small example. Can someone tell me what I should do to
make this compile properly on an ISO-compliant compiler?

template <typename T1, typename T2>
class A
{
public:
T1 t1;
T2 t2;
};

template <typename T1, typename T2>
class B
{
public:
void insert(A<T1, T2> f);
};

template <typename T1>
void B<T1, int>::insert(A<T1, int> f)
{
f.t1 = 0;
f.t2 = 0;
}
template <typename T1, typename T2>
void B<T1, T2>::insert(A<T1, T2> f)
{
f.t1 = 0;
f.t2 = 0;
}

int main()
{
A<int, int> a1;
A<float, float> a2;
B<int, int> b1;
B<float, float> b2;

b1.insert(a1);
b2.insert(a2);

return 0;
}
 
V

Victor Bazarov

I'm confused as to the syntax for partial template specialization.
Below is a very small example. Can someone tell me what I should do to
make this compile properly on an ISO-compliant compiler?

template <typename T1, typename T2>
class A
{
public:
T1 t1;
T2 t2;
};

template <typename T1, typename T2>
class B
{
public:
void insert(A<T1, T2> f);
};

template <typename T1>
void B<T1, int>::insert(A<T1, int> f)
{
f.t1 = 0;
f.t2 = 0;
}

You've attempted to partially specialise a member function. That's not
allowed. You may partially specialise the whole class only.

Besides, I can't see why you'd want to do that. Both functions
are exactly the same.
template <typename T1, typename T2>
void B<T1, T2>::insert(A<T1, T2> f)
{
f.t1 = 0;
f.t2 = 0;
}

int main()
{
A<int, int> a1;
A<float, float> a2;
B<int, int> b1;
B<float, float> b2;

b1.insert(a1);
b2.insert(a2);

return 0;
}

V
 
C

cpunerd

You've attempted to partially specialise a member function. That's not
allowed. You may partially specialise the whole class only.

Besides, I can't see why you'd want to do that. Both functions
are exactly the same.





V

in this case both functions are exactly the same. it is simply a
trivial example to show the problem, which is as you said, you cant
partially specialize a member function. the instance in where i am
trying to do something like this is indeed useful, pity... thanks for
the help though. is there a better idea that you can think of than
making a friend function and specializing the friend function?
 
V

Victor Bazarov

in this case both functions are exactly the same. it is simply a
trivial example to show the problem, which is as you said, you cant
partially specialize a member function. the instance in where i am
trying to do something like this is indeed useful, pity... thanks for
the help though. is there a better idea that you can think of than
making a friend function and specializing the friend function?

One approach:
--------------------------
template<class T, class U> struct A
{
};

template<class U> struct NotInt { enum { yes = 1 }; };
template<> struct NotInt<int> { enum { yes = 0 }; };

template<class T, class U> struct B
{
void foo_generic(A<T,U>& a)
{
cout << "Generic\n";
}

void foo_int(A<T,U>& a)
{
cout << "Specialised\n";
}

void foo(A<T,U>& a)
{
if (NotInt<U>::yes)
foo_generic(a);
else
foo_int(a);
}
};
--------------------------

Another approach:
--------------------------
template<class T, class U> struct A
{
};

template<class U> struct NotInt { static const size_t s = 1; };
template<> struct NotInt<int> { static const size_t s = 0; };

template<class T, class U> struct B
{
template<size_t S>
void foo_helper(A<T,U>& a, int (*) = 0) // OK for non-int 'U'
{
cout << "Generic\n";
}

template<size_t S>
void foo_helper(A<T,U>& a, int (*)[1-S] = 0) // OK only for int 'U'
{
cout << "Specialised\n";
}

void foo(A<T,U>& a)
{
foo_helper<NotInt<U>::s>(a);
}
};
 
A

anon

Victor said:
--------------------------

Another approach:
--------------------------
template<class T, class U> struct B
{
template<size_t S>
void foo_helper(A<T,U>& a, int (*) = 0) // OK for non-int 'U'

template<size_t S>
void foo_helper(A<T,U>& a, int (*)[1-S] = 0) // OK only for int 'U'



Can you explain what are these things? I have not seen them so far.
Under "these things" I meant:
int (*)=0
and
int (*)[1-S]=0
 
V

Victor Bazarov

anon said:
Victor said:
--------------------------

Another approach:
--------------------------
template<class T, class U> struct B
{
template<size_t S>
void foo_helper(A<T,U>& a, int (*) = 0) // OK for non-int 'U'

template<size_t S>
void foo_helper(A<T,U>& a, int (*)[1-S] = 0) // OK only for int
'U'



Can you explain what are these things? I have not seen them so far.
Under "these things" I meant:
int (*)=0
and
int (*)[1-S]=0


It's a pointer to an array of size 'S' and of size '1-S', respectively.
Since I'm not using that pointer for anything, the name of the array is
omitted (it would follow the asterisk), and since I didn't want to put
the value at the place where 'foo_helper' is called, I gave the argument
the default value 0 (null pointer) -- that's the "=0". Alternatively,
I could have written

foo_helper(A<T,U>& a, int (*dummy)) ...

and then call it

foo_helper(a, 0);

(same for the 1-S version of the 'helper').

The technique is called SFINAE. Check it out, it's very convenient.

V
 

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

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top