Template specializations

H

Hendrik Schober

Hi,

this code

#include <iostream>

template< typename T >
struct X {
void f();
};

template<> void X<long>::f() {std::cout << "X<long>::f()\n";}

int main(int, char**)
{
X<long> xi;
xi.f();
return 0;
}

is accepted by GCC4, Comeau Online, and VC7.1.
I thought one cannot specialize only a member of a
class template, but has to specialize the whole
template. It seems that this isn't true?

TIA,

Hendrik Schober

--
(e-mail address removed) is never read
I'm Schobi at suespammers dot org

"Coming back to where you started is not the same as never leaving"
Terry Pratchett
 
B

benben

Hendrik Schober said:
Hi,

this code

#include <iostream>

template< typename T >
struct X {
void f();
};

template<> void X<long>::f() {std::cout << "X<long>::f()\n";}

int main(int, char**)
{
X<long> xi;
xi.f();
return 0;
}

is accepted by GCC4, Comeau Online, and VC7.1.
I thought one cannot specialize only a member of a
class template, but has to specialize the whole
template. It seems that this isn't true?

TIA,

Hendrik Schober

Yes, you can specialize non-template, static data members and member
functions of a class template. However, only full specialization is
supported.

Ben
 
J

John Carson

Hendrik Schober said:
Hi,

this code

#include <iostream>

template< typename T >
struct X {
void f();
};

template<> void X<long>::f() {std::cout << "X<long>::f()\n";}

int main(int, char**)
{
X<long> xi;
xi.f();
return 0;
}

is accepted by GCC4, Comeau Online, and VC7.1.
I thought one cannot specialize only a member of a
class template, but has to specialize the whole
template. It seems that this isn't true?

Correct. From Vandevoorde and Josuttis, C++ Templates, p.190:

"Class templates and function templates can be fully specialized. So can
members of class templates that may be defined outside the body of a class
definition (i.e., member functions, nested classes, and static data
members)." Doubtless, you can find it in the standard as well.
 
B

benben

And btw the following code shows how encapsulation is lost by providing a
member function specialization:

#include <iostream>

template <typename T>
class A
{
private: T t;
public: void f(void){}
};

template<>
void A<int>::f(void)
{
t++; // access private member
std::cout << "t tempered\n";
}

int main(void)
{
A<int> a;
a.f();
}
 
P

puzzlecracker

benben said:
And btw the following code shows how encapsulation is lost by providing a
member function specialization:

#include <iostream>

template <typename T>
class A
{
private: T t;
public: void f(void){}
};

template<>
void A<int>::f(void)
{
t++; // access private member
std::cout << "t tempered\n";
}

int main(void)
{
A<int> a;
a.f();
}


That is very interesting: I didn't know that one can define a
specialization of a member function without having to declare the
specialization version within class definition (declaration that is,
right?). I thought specialization followed overloading phenomenon.

Hmm?

Shouldn't the above instead be (will it work in the following form):

#include <iostream>

template <typename T>
class A {

private:
T t;
public:
void f(void){}
template<>
void f<int>(void)
};

template<>
void A<int>::f(void)
{
t++; // access private member
std::cout << "t tempered\n";
}

int main(void)
{
A<int> a;
a.f();
}
 
G

Greg

benben said:
And btw the following code shows how encapsulation is lost by providing a
member function specialization:

#include <iostream>

template <typename T>
class A
{
private: T t;
public: void f(void){}
};

template<>
void A<int>::f(void)
{
t++; // access private member
std::cout << "t tempered\n";
}

int main(void)
{
A<int> a;
a.f();
}

Isn't A<int>::f() accessing A<int>::t? And aren't the methods of a
class always allowed access to that class's private data members? Why
should we be surprised that this code compiles?

In fact, how would replacing the member template with a class method in
this example really make any difference at all? In short, I don't see
how this example illustrates anything unusual, surprising or at all out
of the ordinary.

Greg
 
A

Alf P. Steinbach

* Greg:
...
how would replacing the member template with a class method in
this example really make any difference at all?

The difference is that with a member template, client code can very easily and
inadvertently access private things, whereas with an ordinary class member
function the client code wouldn't be able to supply an implementation (since
there would already be one), and it wouldn't be natural to try that, either.

In short, I don't see
how this example illustrates anything unusual, surprising or at all out
of the ordinary.

It doesn't. It illustrates a flaw in the C++ type system. There isn't any
lack of flaws in that type system, so it's not unusual, not surprising, not
out of the ordinary: it's just one more thing to keep in mind.
 
B

benben

Shouldn't the above instead be (will it work in the following form):
#include <iostream>

template <typename T>
class A {

private:
T t;
public:
void f(void){}
template<>
void f<int>(void)

The above line seems to intend to provide a specialization of a non-template
member function in an instantiated class template, which, unsurprisingly,
cannot be understood by the compiler.

The code snip I posted showed a specialization of a non-template member
function in a class template, which is doable.

And the point is, anyone can legally abuse any class template by
specializing one or more of its members. Obviously, it will be fool to do
so.

Ben
 
J

John Carson

benben said:
The code snip I posted showed a specialization of a non-template
member function in a class template, which is doable.

And the point is, anyone can legally abuse any class template by
specializing one or more of its members. Obviously, it will be fool
to do so.

I don't think it is either obvious or true. Since the choice of template
arguments for a template class is unlimited (both built-in and user defined
types), the original template class design it unlikely to be appropriate for
all possible template arguments.

The general template provides a default form of the concrete classes
instantiated from it, which hopefully is adequate most of the time, but
there will be plenty of occasions when a different specialisation will be
required. In many cases, the specialisation will be carried out by the
person who wrote the general template. Thus it may be something that occurs
*within* a library. I would agree that 3rd parties should exercise extra
caution when specialising members lest they inadvertently cause problems
with changes to private data.
 
H

Hendrik Schober

Hendrik Schober said:
[...]
I thought one cannot specialize only a member of a
class template, but has to specialize the whole
template. It seems that this isn't true?

Thanks to everyone who answered!

Hendrik Schober

--
(e-mail address removed) is never read
I'm Schobi at suespammers dot org

"Coming back to where you started is not the same as never leaving"
Terry Pratchett
 

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,981
Messages
2,570,188
Members
46,731
Latest member
MarcyGipso

Latest Threads

Top