How to specialize member template function?

P

Peter Koch Larsen

This question has undoubtedly come up zillions of times before, but I've not
been able to google for an answer. My problem can be reproduced as follows:

template<typename T, bool b>
struct bad
{
void f(T const& t);
};

// wanting to specialise for b = true
template<typename T> // Line 15
void bad<T,true>::f()
{
// code goes here
}

// wanting to specialise for b = false
template<typename T>
void bad<T,false>::f()
{
// code goes here
}

This does not work - I receive the following error(Microsoft Beta):
:\cpptest\cpptest.cpp(15) : error C2244: 'bad<T,b>::f' : unable to match
function definition to an existing declaration

s:\cpptest\cpptest.cpp(7) : see declaration of 'bad<T,b>::f'



What did I do wrong?



/Peter
 
S

shez

Peter said:
This question has undoubtedly come up zillions of times before, but I've not
been able to google for an answer. My problem can be reproduced as follows:

template<typename T, bool b>
struct bad
{
void f(T const& t);
};

// wanting to specialise for b = true
template<typename T> // Line 15
void bad<T,true>::f()
{
// code goes here
}

// wanting to specialise for b = false
template<typename T>
void bad<T,false>::f()
{
// code goes here
}

This does not work - I receive the following error(Microsoft Beta):
:\cpptest\cpptest.cpp(15) : error C2244: 'bad<T,b>::f' : unable to match
function definition to an existing declaration

s:\cpptest\cpptest.cpp(7) : see declaration of 'bad<T,b>::f'



What did I do wrong?



/Peter

The function in your class definition takes a const T& argument. Your
specialised versions don't.

-shez-
 
V

Victor Bazarov

Peter said:
This question has undoubtedly come up zillions of times before, but I've not
been able to google for an answer. My problem can be reproduced as follows:

template<typename T, bool b>
struct bad
{
void f(T const& t);
};

// wanting to specialise for b = true
template<typename T> // Line 15
void bad<T,true>::f()
{
// code goes here
}

// wanting to specialise for b = false
template<typename T>
void bad<T,false>::f()
{
// code goes here
}

This does not work - I receive the following error(Microsoft Beta):
:\cpptest\cpptest.cpp(15) : error C2244: 'bad<T,b>::f' : unable to match
function definition to an existing declaration

s:\cpptest\cpptest.cpp(7) : see declaration of 'bad<T,b>::f'



What did I do wrong?

You need to specialise the class first. Partial specialisation of
function templates by themselves is not allowed.

What if you do

template<typename T, bool b>
struct notsobad
{
private:
void f_true(T const& t);
void f_false(T const& t);
public:
void f(T const& t) {
if (b) f_true(t);
else f_false(t);
}
};

Yes, it has some code bloat, is that the primary concern?

Victor
 
P

Peter Koch Larsen

Victor Bazarov said:
You need to specialise the class first. Partial specialisation of
function templates by themselves is not allowed.

What if you do

template<typename T, bool b>
struct notsobad
{
private:
void f_true(T const& t);
void f_false(T const& t);
public:
void f(T const& t) {
if (b) f_true(t);
else f_false(t);
}
};

Yes, it has some code bloat, is that the primary concern?

Victor
Hi Victor

No - the code bloat is sort of okay. The problem is that depending on the
boolean template parameter, only one of the functions will compile. If b is
true, f_false in your example would compile with an error and vice versa.
It looks like I need some help from boosts mpl.
/Peter
 
P

Peter Koch Larsen

shez said:
The function in your class definition takes a const T& argument. Your
specialised versions don't.

Hi shez.

I just KNEW i should have done a copy&paste, and actually I did so - getting
a weird font in outlook express. That made me retype it. In the original
example, the signature of the f's were correct. Not so in my untested code
;-(

/Peter
 
V

Victor Bazarov

Peter said:
Victor Bazarov said:
[..]
What if you do

template<typename T, bool b>
struct notsobad
{
private:
void f_true(T const& t);
void f_false(T const& t);
public:
void f(T const& t) {
if (b) f_true(t);
else f_false(t);
}
};

Yes, it has some code bloat, is that the primary concern?

Victor

Hi Victor

No - the code bloat is sort of okay. The problem is that depending on the
boolean template parameter, only one of the functions will compile. If b is
true, f_false in your example would compile with an error and vice versa.

I am not sure I understand the "problem". Are you implying that my
example code is not going to compile or are you saying that you would
*like* it not to compile?
It looks like I need some help from boosts mpl.

Probably. I am not that familiar with Boost.

V
 
P

Peter Koch Larsen

Victor Bazarov said:
Peter said:
Victor Bazarov said:
[..]
What if you do

template<typename T, bool b>
struct notsobad
{
private:
void f_true(T const& t);
void f_false(T const& t);
public:
void f(T const& t) {
if (b) f_true(t);
else f_false(t);
}
};

Yes, it has some code bloat, is that the primary concern?

Victor

Hi Victor

No - the code bloat is sort of okay. The problem is that depending on the
boolean template parameter, only one of the functions will compile. If b
is true, f_false in your example would compile with an error and vice
versa.

I am not sure I understand the "problem". Are you implying that my
example code is not going to compile or are you saying that you would
*like* it not to compile?
None of the above. Imagine that my spacialisation with b = false only is
used for integer types, and f_false contains the code T i = T(2) % T(4);
Now, when i specialise for e.g. a std::string, the code wont compile
(std::string i = std::string(2) % std::string(4) is not a legal statement).
And this is exactly my problem.

/Peter
 
A

Andrey Tarasevich

Peter said:
This question has undoubtedly come up zillions of times before, but I've not
been able to google for an answer. My problem can be reproduced as follows:

template<typename T, bool b>
struct bad
{
void f(T const& t);
};

// wanting to specialise for b = true
template<typename T> // Line 15
void bad<T,true>::f()
{
// code goes here
}

// wanting to specialise for b = false
template<typename T>
void bad<T,false>::f()
{
// code goes here
}

This does not work - I receive the following error(Microsoft Beta):
:\cpptest\cpptest.cpp(15) : error C2244: 'bad<T,b>::f' : unable to match
function definition to an existing declaration

s:\cpptest\cpptest.cpp(7) : see declaration of 'bad<T,b>::f'

What did I do wrong?
...

It is just that there's no such feature in C++. You can provide
_explicit_ specialization of non-template member function of template
class, but you can't do the same in case of _partial_ specialization.
Partial specialization in C++ is only allowed in class template
declarations.
 
V

Victor Bazarov

Peter said:
"Victor Bazarov" <[email protected]> skrev i en meddelelse

[..]
What if you do

template<typename T, bool b>
struct notsobad
{
private:
void f_true(T const& t);
void f_false(T const& t);
public:
void f(T const& t) {
if (b) f_true(t);
else f_false(t);
}
};
[..] Imagine that my spacialisation with b = false only is
used for integer types, and f_false contains the code T i = T(2) % T(4);
Now, when i specialise for e.g. a std::string, the code wont compile
(std::string i = std::string(2) % std::string(4) is not a legal statement).
And this is exactly my problem.

Ah, got it.

How about
------------------------------------------
template<bool b> struct AA
{
template<class T> static void foo(T const& t);
};

template<> template<class T> void AA<true>::foo(T const& t)
{
t % t;
}

template<> template<class T> void AA<false>::foo(T const& t)
{
t + t;
}

template<class T, bool b> struct A
{
void foo(T const& t) { AA<b>::foo(t); }
};

int main()
{
A<int,true> ait;
A<double,false> adf;

ait.foo(0);
adf.foo(0);

return 0;
}
---------------- just a thought...

Victor
 
P

Peter Koch Larsen

Hi Victor,

Just perfect - thanks!

/Peter
Victor Bazarov said:
Peter said:
"Victor Bazarov" <[email protected]> skrev i en meddelelse
[..] Imagine that my spacialisation with b = false only is used for
integer types, and f_false contains the code T i = T(2) % T(4);
Now, when i specialise for e.g. a std::string, the code wont compile
(std::string i = std::string(2) % std::string(4) is not a legal
statement). And this is exactly my problem.

Ah, got it.

How about
------------------------------------------
template<bool b> struct AA
{
template<class T> static void foo(T const& t);
};

template<> template<class T> void AA<true>::foo(T const& t)
{
t % t;
}

template<> template<class T> void AA<false>::foo(T const& t)
{
t + t;
}

template<class T, bool b> struct A
{
void foo(T const& t) { AA<b>::foo(t); }
};

int main()
{
A<int,true> ait;
A<double,false> adf;

ait.foo(0);
adf.foo(0);

return 0;
}
---------------- just a thought...

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

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,131
Latest member
IsiahLiebe
Top