By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,655 Members | 959 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,655 IT Pros & Developers. It's quick & easy.

How to partial specialize a template member function in a template class?

P: n/a
Hi,

I want to partial specialize the member function doit. But it doesn't
work. Could you please help me to figure out what is wrong?

Thanks,
Peng

template <typename T>
class A {
public:
A() {}
template <typename T1>
void doit();
};

template <>
template <typename T>
void A<T>::doit<double>() {
std::cout << "double" << std::endl;
}
int main() {
A<doublea;
a.doit<double>();
}

Mar 13 '07 #1
Share this Question
Share on Google+
16 Replies


P: n/a
Pe*******@gmail.com wrote:
I want to partial specialize the member function doit. But it doesn't
work. Could you please help me to figure out what is wrong?
Specialisations of class members are not allowed without first
specialising the class itself.

What problem are you trying to solve?
>
Thanks,
Peng

template <typename T>
class A {
public:
A() {}
template <typename T1>
void doit();
};

template <>
template <typename T>
void A<T>::doit<double>() {
std::cout << "double" << std::endl;
}
int main() {
A<doublea;
a.doit<double>();
}
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Mar 13 '07 #2

P: n/a
Pe*******@gmail.com wrote:
Hi,

I want to partial specialize the member function doit. But it doesn't
work. Could you please help me to figure out what is wrong?

Thanks,
Peng

template <typename T>
class A {
public:
A() {}
template <typename T1>
void doit();
};

template <>
template <typename T>
void A<T>::doit<double>() {
std::cout << "double" << std::endl;
}
int main() {
A<doublea;
a.doit<double>();
}
It really depends on the requirements of your program.
If your template member function has a distinct
signature (your current example does not) then you can
use simple function overloading to solve it for you
as shown in the following example. Otherwise, you will
need to specialize your primary template as Victor
suggests.

------------------------------------------------------
#include <iostream>

using namespace std;

template <typename T>
class A {
public:
A() {}
template <typename T1>
void doit( T1 * p ) { cout << "Template" << endl; }

void doit( void * p) { cout << "Specialized" << endl;}
};

int
main()
{
A<intfoo;
int *bar;
void *baz;
foo.doit( bar );
foo.doit( baz );
}
-------------------------------------------
This program prints:
Template
Specialized
Mar 13 '07 #3

P: n/a
On Mar 13, 5:23 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
PengYu...@gmail.com wrote:
I want to partial specialize the member function doit. But it doesn't
work. Could you please help me to figure out what is wrong?

Specialisations of class members are not allowed without first
specialising the class itself.

What problem are you trying to solve?
The problem that I encountered was that I tried to expand the
interface of a member function of a template class. A bool argument
was added to the member function.

Later on, I found that it is better not to use a bool argument,
because it results in runtime overhead. I want to supply it as an
template argument, which is resolved at compile time. Then the runtime
overhead of conditional branches can be avoid. However, it seems the
problem is not that easy.

I'm not sure how to specialize the class first. Could you please show
it to me? BTW, I modify the examples to reflect my intent better. The
first one is with branch. I want to modify it to eliminate the branch
by template specialization. I want the solution with as less
modification to the original code as possible. This requirement makes
the refactoring process easier.

/////////////code with branch
#include <iostream>
template <typename T>
class A {
public:
A(T t) : _t(t) {}
T doit(bool b) {
if(b) return _t;
else return - _t;
}
private:
T _t;
};

int main() {
A<doublea(10);

std::cout << a.doit(true) << std::endl;
}
/////////////end code with branch

////////////code with template(not working)
#include <iostream>
template <typename T>
class A {
public:
A(T t) : _t(t) {}
template <bool B>
T doit();// it was a function without any template
// argument, which only return _t;
private:
T _t;
};

template <>
template <typename T>
T A<T>::doit<true>() {
return _t;
}

template <>
template <typename T>
T A<T>::doit<false>() {
return - _t;
}

int main() {
A<doublea(10);

std::cout << a.doit() << std::endl;
}

Mar 14 '07 #4

P: n/a
Pe*******@gmail.com wrote:
>
////////////code with template(not working)
#include <iostream>
template <typename T>
class A {
public:
A(T t) : _t(t) {}
template <bool B>
T doit();// it was a function without any template
// argument, which only return _t;
private:
T _t;
};

template <>
template <typename T>
T A<T>::doit<true>() {
return _t;
}

template <>
template <typename T>
T A<T>::doit<false>() {
return - _t;
}

int main() {
A<doublea(10);

std::cout << a.doit() << std::endl;
}
Instead of using template member functions, have you
considered just having two regular member functions
that do what you want.
------------------------------------------------------
template<typename T>
class Test
{
public:

T fooPlus() { return m_data; }
T fooMinus() { return -m_data; }

private:
T m_data;
};
-----------------------------------------------------

Can you show me a simple main() driver that actually
uses what you want? In your current main:
> A<doublea(10);

std::cout << a.doit() << std::endl;
This does not work since
a.doit() does not map to anything proper unless you do
a.doit<true>() or a.doit<false>(). But if you are explicitly
specifying true or false, it is not different from doing
a.fooPlus() or a.fooMinus().

Can you show me a situation where you need this special
case you are talking about?
Mar 14 '07 #5

P: n/a
On Mar 13, 7:59 pm, Piyo <cybermax...@yahoo.comwrote:
PengYu...@gmail.com wrote:
////////////code with template(not working)
#include <iostream>
template <typename T>
class A {
public:
A(T t) : _t(t) {}
template <bool B>
T doit();// it was a function without any template
// argument, which only return _t;
private:
T _t;
};
template <>
template <typename T>
T A<T>::doit<true>() {
return _t;
}
template <>
template <typename T>
T A<T>::doit<false>() {
return - _t;
}
int main() {
A<doublea(10);
std::cout << a.doit() << std::endl;
}

Instead of using template member functions, have you
considered just having two regular member functions
that do what you want.
------------------------------------------------------
template<typename T>
class Test
{
public:

T fooPlus() { return m_data; }
T fooMinus() { return -m_data; }

private:
T m_data;};

-----------------------------------------------------

Can you show me a simple main() driver that actually
uses what you want? In your current main:
A<doublea(10);
std::cout << a.doit() << std::endl;

This does not work since
a.doit() does not map to anything proper unless you do
a.doit<true>() or a.doit<false>(). But if you are explicitly
specifying true or false, it is not different from doing
a.fooPlus() or a.fooMinus().

Can you show me a situation where you need this special
case you are talking about?
The real situation comes when some other template function (f1) call
the doit member function with a template argument.
If I have a.fooPlus() or a.fooMinus(), I can not really template f1
function.
With a.doit<true>() and a.doit<false>(), I can. See below.

template <bool B>
void f1(A<double&a, many argument...) {
many code here...
a.doit<B>();
many code here...

}

Mar 14 '07 #6

P: n/a
Pe*******@gmail.com wrote:
[..]
The real situation comes when some other template function (f1) call
the doit member function with a template argument.
If I have a.fooPlus() or a.fooMinus(), I can not really template f1
function.
With a.doit<true>() and a.doit<false>(), I can. See below.

template <bool B>
void f1(A<double&a, many argument...) {
many code here...
a.doit<B>();
What's stopping you from writing

if (B)
a.doitTrue();
else
a.doitFalse();

?
many code here...

}
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Mar 14 '07 #7

P: n/a
Pe*******@gmail.com wrote:
The real situation comes when some other template function (f1) call
the doit member function with a template argument.
If I have a.fooPlus() or a.fooMinus(), I can not really template f1
function.
With a.doit<true>() and a.doit<false>(), I can. See below.

template <bool B>
void f1(A<double&a, many argument...) {
many code here...
a.doit<B>();
many code here...

}
I am not convinced that it is such a great idea to do this since
there is a lot of hoops and scaffolding to create just to do what
you are thinking. There might be a better solution directly to your
problem but I cannot think of it right now. Here is an example of
specializing a friend class instead to serve as your accessor.

-----------------------------------------------------------------
template<typename Tclass Test;

template<bool enable, typename Type>
struct getData;

template<typename Type>
struct getData<true,Type>
{
Type operator()( Test<Type&b )
{
return b.m_data;
}
};

template<typename Type>
struct getData<false, Type>
{
Type operator()( Test<Type&b )
{
return -b.m_data;
}
};
template<typename T>
class Test
{
public:

template<bool enable, typename Type friend struct getData;

private:
T m_data;
};

template <bool B>
double f1( Test<double>& a )
{
getData<B, doubleaccessor;
return accessor( a );
}

int
main()
{
Test<doublefoo;
f1<true>( foo );
f1<false>( foo );
}
Mar 14 '07 #8

P: n/a
On Mar 14, 1:11 pm, Piyo <cybermax...@yahoo.comwrote:
PengYu...@gmail.com wrote:
The real situation comes when some other template function (f1) call
the doit member function with a template argument.
If I have a.fooPlus() or a.fooMinus(), I can not really template f1
function.
With a.doit<true>() and a.doit<false>(), I can. See below.
template <bool B>
void f1(A<double&a, many argument...) {
many code here...
a.doit<B>();
many code here...
}

I am not convinced that it is such a great idea to do this since
there is a lot of hoops and scaffolding to create just to do what
you are thinking. There might be a better solution directly to your
problem but I cannot think of it right now. Here is an example of
specializing a friend class instead to serve as your accessor.

-----------------------------------------------------------------
template<typename Tclass Test;

template<bool enable, typename Type>
struct getData;

template<typename Type>
struct getData<true,Type>
{
Type operator()( Test<Type&b )
{
return b.m_data;
}

};

template<typename Type>
struct getData<false, Type>
{
Type operator()( Test<Type&b )
{
return -b.m_data;
}

};

template<typename T>
class Test
{
public:

template<bool enable, typename Type friend struct getData;

private:
T m_data;

};

template <bool B>
double f1( Test<double>& a )
{
getData<B, doubleaccessor;
return accessor( a );

}

int
main()
{
Test<doublefoo;
f1<true>( foo );
f1<false>( foo );

}
This is essentially how I solved the problem. However, the problem
still comes from software refactoring.

Suppose, original, my class "A" does not have any template argument as
shown in the following example. Later on I find out I need to change
int to a template argument T. I can turn "A" into a templated class as
if "A" does not have any template member function. I have to rely on
the tricks in your example, which makes the refactoring process more
expensive. I'm wondering if there is anything that can be changed in
the C++ language to make this process easier.

#include <iostream>

class A {
public:
A(int t) : _t(t) {}
template <bool B>
int doit();
private:
int _t;
};

template <>
int A::doit<true>() {
return _t;

}

template <>
int A::doit<false>() {
return - _t;
}

int main ()
{
A a(10);
std::cout << a.doit<true>() << std::endl;
std::cout << a.doit<false>() << std::endl;
}

Mar 14 '07 #9

P: n/a
On Mar 13, 10:29 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
PengYu...@gmail.com wrote:
[..]
The real situation comes when some other template function (f1) call
the doit member function with a template argument.
If I have a.fooPlus() or a.fooMinus(), I can not really template f1
function.
With a.doit<true>() and a.doit<false>(), I can. See below.
template <bool B>
void f1(A<double&a, many argument...) {
many code here...
a.doit<B>();

What's stopping you from writing

if (B)
a.doitTrue();
else
a.doitFalse();

?
many code here...
}
In principle, it is OK. But this would result in less readable code.
BTW, may I ask if the branch is resolved at compile time or runtime?

Also, when expression template comes in, we might have to do something
like
if (B)
many_thing_before_in_the_expression_template ....
a.doitTrue()//note there is no ";"
....many_thing_after_in_the_expression_template;
else
many_thing_before_in_the_expression_template ....
a.doitFalse()//note there is no ";"
....many_thing_after_in_the_expression_template;
It is better if I write like the following:

many_thing_before_in_the_expression_template ....
a.doit<B>()//note there is no ";"
....many_thing_after_in_the_expression_template;

Mar 14 '07 #10

P: n/a
Pe*******@gmail.com wrote:
On Mar 13, 10:29 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
>PengYu...@gmail.com wrote:
>>[..]
The real situation comes when some other template function (f1) call
the doit member function with a template argument.
If I have a.fooPlus() or a.fooMinus(), I can not really template f1
function.
With a.doit<true>() and a.doit<false>(), I can. See below.
>>template <bool B>
void f1(A<double&a, many argument...) {
many code here...
a.doit<B>();

What's stopping you from writing

if (B)
a.doitTrue();
else
a.doitFalse();

?
>>many code here...
>>}

In principle, it is OK. But this would result in less readable code.
Really?
BTW, may I ask if the branch is resolved at compile time or runtime?
That's unspecified. Most compilers will remove unnecessary code.
>
Also, when expression template comes in, we might have to do something
like
if (B)
many_thing_before_in_the_expression_template ....
a.doitTrue()//note there is no ";"
....many_thing_after_in_the_expression_template;
else
many_thing_before_in_the_expression_template ....
a.doitFalse()//note there is no ";"
....many_thing_after_in_the_expression_template;
It is better if I write like the following:

many_thing_before_in_the_expression_template ....
a.doit<B>()//note there is no ";"
....many_thing_after_in_the_expression_template;
Uh... This is all fine and dandy, but why can't you do

many_thing_before_in_the_expression_template ....
( B ? a.doitIfBTrue() // note there is no ";"
: a.doitIfBIsFalse() ) // note there is no ";"
....many_thing_after_in_the_expression_template;

?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Mar 14 '07 #11

P: n/a
On Mar 14, 4:28 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
PengYu...@gmail.com wrote:
On Mar 13, 10:29 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
PengYu...@gmail.com wrote:
[..]
The real situation comes when some other template function (f1) call
the doit member function with a template argument.
If I have a.fooPlus() or a.fooMinus(), I can not really template f1
function.
With a.doit<true>() and a.doit<false>(), I can. See below.
>template <bool B>
void f1(A<double&a, many argument...) {
many code here...
a.doit<B>();
What's stopping you from writing
if (B)
a.doitTrue();
else
a.doitFalse();
?
>many code here...
>}
In principle, it is OK. But this would result in less readable code.

Really?
BTW, may I ask if the branch is resolved at compile time or runtime?

That's unspecified. Most compilers will remove unnecessary code.


Also, when expression template comes in, we might have to do something
like
if (B)
many_thing_before_in_the_expression_template ....
a.doitTrue()//note there is no ";"
....many_thing_after_in_the_expression_template;
else
many_thing_before_in_the_expression_template ....
a.doitFalse()//note there is no ";"
....many_thing_after_in_the_expression_template;
It is better if I write like the following:
many_thing_before_in_the_expression_template ....
a.doit<B>()//note there is no ";"
....many_thing_after_in_the_expression_template;

Uh... This is all fine and dandy, but why can't you do

many_thing_before_in_the_expression_template ....
( B ? a.doitIfBTrue() // note there is no ";"
: a.doitIfBIsFalse() ) // note there is no ";"
....many_thing_after_in_the_expression_template;
Yes, you can.

In my expression, I have one instance of the following expression. But
what if you have many instances, it will make the expression less
readable. After all, a.doit<B>() is much more readable than if
statement and ?: operator. And it requires less changes from the user
side than using if statement and ?: operator.
Better readability makes the program easier to maintain. Less changes
make the program easier to be refactored.

( B ? a.doitIfBTrue() // note there is no ";"
: a.doitIfBIsFalse() ) // note there is no ";"

Mar 15 '07 #12

P: n/a
On Mar 13, 10:29 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
PengYu...@gmail.com wrote:
[..]
The real situation comes when some other template function (f1) call
the doit member function with a template argument.
If I have a.fooPlus() or a.fooMinus(), I can not really template f1
function.
With a.doit<true>() and a.doit<false>(), I can. See below.
template <bool B>
void f1(A<double&a, many argument...) {
many code here...
a.doit<B>();

What's stopping you from writing

if (B)
a.doitTrue();
else
a.doitFalse();

?
many code here...
}
Just to make sure. There is no runtime overhead in this code, right?
Is the branch resolved at compile time?

Thanks,
Peng

Mar 15 '07 #13

P: n/a
Pe*******@gmail.com wrote:
On Mar 13, 10:29 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
>PengYu...@gmail.com wrote:
>>[..]
The real situation comes when some other template function (f1) call
the doit member function with a template argument.
If I have a.fooPlus() or a.fooMinus(), I can not really template f1
function.
With a.doit<true>() and a.doit<false>(), I can. See below.
>>template <bool B>
void f1(A<double&a, many argument...) {
many code here...
a.doit<B>();

What's stopping you from writing

if (B)
a.doitTrue();
else
a.doitFalse();

?
>>many code here...
>>}

Just to make sure. There is no runtime overhead in this code, right?
Is the branch resolved at compile time?
Just to make sure. This is unspecified in the language Standard.

But I have a question: WHAT runtime overhead? From where? You ask
as if you know that it might be there, meaning, you have seen the
overhead in a similar situation. Care to elaborate?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Mar 15 '07 #14

P: n/a
Pe*******@gmail.com wrote:
On Mar 14, 4:28 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
>PengYu...@gmail.com wrote:
>>On Mar 13, 10:29 pm, "Victor Bazarov" <v.Abaza...@comAcast.net>
wrote:
PengYu...@gmail.com wrote:
[..]
The real situation comes when some other template function (f1)
call the doit member function with a template argument.
If I have a.fooPlus() or a.fooMinus(), I can not really template
f1 function.
With a.doit<true>() and a.doit<false>(), I can. See below.
>>>>template <bool B>
void f1(A<double&a, many argument...) {
many code here...
a.doit<B>();
>>>What's stopping you from writing
>>> if (B)
a.doitTrue();
else
a.doitFalse();
>>>?
>>>>many code here...
>>>>}
>>In principle, it is OK. But this would result in less readable code.

Really?
>>BTW, may I ask if the branch is resolved at compile time or runtime?

That's unspecified. Most compilers will remove unnecessary code.


>>Also, when expression template comes in, we might have to do
something like
if (B)
many_thing_before_in_the_expression_template ....
a.doitTrue()//note there is no ";"
....many_thing_after_in_the_expression_template;
else
many_thing_before_in_the_expression_template ....
a.doitFalse()//note there is no ";"
....many_thing_after_in_the_expression_template;
>>It is better if I write like the following:
>> many_thing_before_in_the_expression_template ....
a.doit<B>()//note there is no ";"
....many_thing_after_in_the_expression_template;

Uh... This is all fine and dandy, but why can't you do

many_thing_before_in_the_expression_template ....
( B ? a.doitIfBTrue() // note there is no ";"
: a.doitIfBIsFalse() ) // note there is no ";"
....many_thing_after_in_the_expression_template;

Yes, you can.

In my expression, I have one instance of the following expression. But
what if you have many instances, it will make the expression less
readable. After all, a.doit<B>() is much more readable than if
statement and ?: operator. And it requires less changes from the user
side than using if statement and ?: operator.
Better readability makes the program easier to maintain. Less changes
make the program easier to be refactored.
Oh, bullshit (pardon my French).
If you have "many_thing_before_in_the_blah" and then
"many_thing_after_in_the_blah", what readability are you trying to
claim here?
>
( B ? a.doitIfBTrue() // note there is no ";"
: a.doitIfBIsFalse() ) // note there is no ";"
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Mar 15 '07 #15

P: n/a
On Mar 14, 10:35 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
PengYu...@gmail.com wrote:
On Mar 14, 4:28 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
PengYu...@gmail.com wrote:
On Mar 13, 10:29 pm, "Victor Bazarov" <v.Abaza...@comAcast.net>
wrote:
PengYu...@gmail.com wrote:
[..]
The real situation comes when some other template function (f1)
call the doit member function with a template argument.
If I have a.fooPlus() or a.fooMinus(), I can not really template
f1 function.
With a.doit<true>() and a.doit<false>(), I can. See below.
>>>template <bool B>
void f1(A<double&a, many argument...) {
many code here...
a.doit<B>();
>>What's stopping you from writing
>> if (B)
a.doitTrue();
else
a.doitFalse();
>>?
>>>many code here...
>>>}
>In principle, it is OK. But this would result in less readable code.
Really?
>BTW, may I ask if the branch is resolved at compile time or runtime?
That's unspecified. Most compilers will remove unnecessary code.
>Also, when expression template comes in, we might have to do
something like
if (B)
many_thing_before_in_the_expression_template ....
a.doitTrue()//note there is no ";"
....many_thing_after_in_the_expression_template;
else
many_thing_before_in_the_expression_template ....
a.doitFalse()//note there is no ";"
....many_thing_after_in_the_expression_template;
>It is better if I write like the following:
> many_thing_before_in_the_expression_template ....
a.doit<B>()//note there is no ";"
....many_thing_after_in_the_expression_template;
Uh... This is all fine and dandy, but why can't you do
many_thing_before_in_the_expression_template ....
( B ? a.doitIfBTrue() // note there is no ";"
: a.doitIfBIsFalse() ) // note there is no ";"
....many_thing_after_in_the_expression_template;
Yes, you can.
In my expression, I have one instance of the following expression. But
what if you have many instances, it will make the expression less
readable. After all, a.doit<B>() is much more readable than if
statement and ?: operator. And it requires less changes from the user
side than using if statement and ?: operator.
Better readability makes the program easier to maintain. Less changes
make the program easier to be refactored.

Oh, bullshit (pardon my French).
Please be careful when you use these words in the groups.
If you have "many_thing_before_in_the_blah" and then
"many_thing_after_in_the_blah", what readability are you trying to
claim here?
Maybe these things is not very readable in your opinion. But let's
assume we can not do anything to change it. Or if needed, we can spend
some effort to change them to make it more readable.
( B ? a.doitIfBTrue() // note there is no ";"
: a.doitIfBIsFalse() ) // note there is no ";"
But still the above things are less readable than a.doit<B>().

Remember the problem comes from the fact that partial specialization
of a template member function of a regular class is different from
that of a templated class. I'm wondering why the C++ standard make
this kind of distinction. Would this make code refactoring more
painful.

Thanks,
Peng

Mar 15 '07 #16

P: n/a
Pe*******@gmail.com wrote:
On Mar 14, 10:35 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
[..]
>> ( B ? a.doitIfBTrue() // note there is no ";"
: a.doitIfBIsFalse() ) // note there is no ";"

But still the above things are less readable than a.doit<B>().
Well, wrap them in a function, and pass 'B' [and 'a' if need be] to it:

a.doitWith(B)

or

doitWith(a, B)

or whatever else. Don't be so hell-bent on using 'a.doit<B>()'. What
is the point of the exercise? Is it to prove the impossibility? I am
simply trying to show a way to do it, a work-around.

Maintainability, readability, are both very subjective. Why insist on
non-existent (albeit "more readable") way of doing things, when there
is another, simple (and not REALLY less readable) way?
Remember the problem comes from the fact that partial specialization
of a template member function of a regular class is different from
that of a templated class. I'm wondering why the C++ standard make
this kind of distinction. Would this make code refactoring more
painful.
I am not sure why one's not allowed to specialize a member template
of a class template without first specializing the class template.
You could ask about the rationale for it in comp.std.c++.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Mar 15 '07 #17

This discussion thread is closed

Replies have been disabled for this discussion.