Template Specialisation

J

johnbrown105

Is it possible to force the compiler to use a generic template rather
than a
matching specialisation?

Consider the following:

////////////////////////////////////////// template.cpp starts here

#include <iostream>
#include <ostream>


template<class T>
void f(T t)
{
std::cout << "template<T> void f(T t) called: t == " << t
<< std::endl;
}


template<> void f<int>(int i)
{
std::cout << "specialisation void f<int>(int i) called: i == "
<< i << std::endl;
}

void f(int j){
std::cout << "overloaded void f(int j) called: j == "
<< j << std::endl;
}

int main()
{
f(1); // simple function matches before template
f<int>(2); // specialisation
f<>(3); // no need to spell out <int>, because it *must* be int
f('4'); // template matches - f<char>(char)
return 0;
}

////////////////////////////////////////// template.cpp ends here

Is there a way to call f with an int parameter so that the generic
f<T>
is called instead of the f<int> specialisation?

I don't want to do this, and I cannot think of a reason for doing it.
I'm just wondering.
 
M

Matthias Buelow

Is there a way to call f with an int parameter so that the generic
f<T> is called instead of the f<int> specialisation?

There is no f<T>, a template is kind of a compiler macro, the compiler
generates functions only if you instantiate a template (expand the
macro, in other words).
 
J

johnbrown105

There is no f<T>, a template is kind of a compiler macro, the compiler
generates functions only if you instantiate a template (expand the
macro, in other words).

I understand that. Consider the output of the program that I posted:

overloaded void f(int j) called: j == 1
specialization void f<int>(int i) called: i == 2
specialization void f<int>(int i) called: i == 3
template<T> void f(T t) called: t == 4

Is there a way to write a call to f(5), so that the output would be:
template<T> void f(T t) called: t == 5
Never mind the semantic accuracy or elegance (or lack thereof!) of
what I wrote. If this is what we are aiming for, I suppose the
question
would be:

Is there a way to make the compiler generate its own instantiation,
rather than use the explicit one that I provided? When asked this way,
it would seem that the answer would be no, because if it generated its
own instantiation, it would be a duplicate symbol, because mine
already
exists.

Still, one never knows if the Powers That Be thought of some clever
reason to allow this, that mere mortals such as myself could not.
That's why I'm asking.
 
T

Tadeusz B. Kopec

Is it possible to force the compiler to use a generic template rather
than a
matching specialisation?

Consider the following:

////////////////////////////////////////// template.cpp starts here

#include <iostream>
#include <ostream>


template<class T>
void f(T t)
{
std::cout << "template<T> void f(T t) called: t == " << t
<< std::endl;
}


template<> void f<int>(int i)
{
std::cout << "specialisation void f<int>(int i) called: i == "
<< i << std::endl;
}

void f(int j){
std::cout << "overloaded void f(int j) called: j == "
<< j << std::endl;
}

int main()
{
f(1); // simple function matches before template f<int>(2);
// specialisation
f<>(3); // no need to spell out <int>, because it *must* be int
f('4'); // template matches - f<char>(char) return 0;
}

////////////////////////////////////////// template.cpp ends here

Is there a way to call f with an int parameter so that the generic f<T>
is called instead of the f<int> specialisation?

f(3u) or f<unsigned>(3) would be OK?
 
J

John Scheldroup

I understand that. Consider the output of the program that I posted:

overloaded void f(int j) called: j == 1
specialization void f<int>(int i) called: i == 2
specialization void f<int>(int i) called: i == 3
template<T> void f(T t) called: t == 4

Is there a way to write a call to f(5), so that the output would be:
template<T> void f(T t) called: t == 5
Never mind the semantic accuracy or elegance (or lack thereof!) of
what I wrote. If this is what we are aiming for, I suppose the
question
would be:

Is there a way to make the compiler generate its own instantiation,
rather than use the explicit one that I provided? When asked this way,
it would seem that the answer would be no, because if it generated its
own instantiation, it would be a duplicate symbol, because mine
already
exists.

Still, one never knows if the Powers That Be thought of some clever
reason to allow this, that mere mortals such as myself could not.
That's why I'm asking.

Now suppose you have some sort of container class called
dweeblist that is filled with dweeb objects. A pointer to the
current dweeb object is produced with member function current().
You can define a function that applies a member function
(which is passed as an argument) to all dweeb objects in dweeblist
and then call this function for dweeblist dl like this:

#include <iostream.h>

class dweeb {
public:
void spin () {cout << "spinning!" << endl; }
void dodge () {cout << "dodging!" << endl; }
void feint () {cout << "feinting!" << endl; }
};

template<int sz> class dweeblist {
dweeb list [sz];
int cursor;
public:
dweeblist () : cursor(0) {}
void reset () { cursor = 0; }
dweeb * current () { return &list [cursor]; }
void next () { cursor++; }
int end () { return cursor >= sz; }
void apply (void (dweeb::* df) () ) {
reset ();
while ( !end() ) {
(current ()->*df) ();
next ();
}
}
};

void main () {
dweeblist<7> dl;
dl.apply(&dweeb::spin);
dl.apply(&dweeb::dodge);
dl.apply(&dweeb::feint);
}

Typically, the kind of function you'd want to apply()
to every object in a list would be something like draw().
for CAD.

Pointers to members have fairly limited use, but they
can be quite helpful when you want to delay the selection
of a specific function until the program is running.

C++ Inside & Out
Bruce Eckel
 
J

johnbrown105

f(3u) or f<unsigned>(3) would be OK?


Not really. An unsigned int is, of course, not the same as a signed
int.
Naturally, it would generate and call f(char). I want to find out if,
even though I have provided f<int>(int), there was a way to make the
compiler generate f(int) using the f<T>(int T) template. This function
would, of course, be different from the one that I provided.

As I said in my original post, I don't actually want to do this.
Neither do
I foresee a need to do it, so don't think too hard about it.
 
J

johnbrown105

I understand that. Consider the output of the program that I posted:
overloaded void f(int j) called: j == 1
specialization void f<int>(int i) called: i == 2
specialization void f<int>(int i) called: i == 3
template<T> void f(T t) called: t == 4
Is there a way to write a call to f(5), so that the output would be:
template<T> void f(T t) called: t == 5
Never mind the semantic accuracy or elegance (or lack thereof!) of
what I wrote. If this is what we are aiming for, I suppose the
question
would be:
Is there a way to make the compiler generate its own instantiation,
rather than use the explicit one that I provided? When asked this way,
it would seem that the answer would be no, because if it generated its
own instantiation, it would be a duplicate symbol, because mine
already
exists.
Still, one never knows if the Powers That Be thought of some clever
reason to allow this, that mere mortals such as myself could not.
That's why I'm asking.

Now suppose you have some sort of container class called
dweeblist that is filled with dweeb objects. A pointer to the
current dweeb object is produced with member function current().
You can define a function that applies a member function
(which is passed as an argument) to all dweeb objects in dweeblist
and then call this function for dweeblist dl like this:

#include <iostream.h>

class dweeb {
public:
void spin () {cout << "spinning!" << endl; }
void dodge () {cout << "dodging!" << endl; }
void feint () {cout << "feinting!" << endl; }

};

template<int sz> class dweeblist {
dweeb list [sz];
int cursor;
public:
dweeblist () : cursor(0) {}
void reset () { cursor = 0; }
dweeb * current () { return &list [cursor]; }
void next () { cursor++; }
int end () { return cursor >= sz; }
void apply (void (dweeb::* df) () ) {
reset ();
while ( !end() ) {
(current ()->*df) ();
next ();
}
}

};

void main () {
dweeblist<7> dl;
dl.apply(&dweeb::spin);
dl.apply(&dweeb::dodge);
dl.apply(&dweeb::feint);

}

Typically, the kind of function you'd want to apply()
to every object in a list would be something like draw().
for CAD.

Pointers to members have fairly limited use, but they
can be quite helpful when you want to delay the selection
of a specific function until the program is running.

C++ Inside & Out
Bruce Eckel

I'm not sure how this relates to my question. The reference to
Bruce Eckel is interesting, as I am currently working through
the chapter on templates in his "Thinking in C++ Vol. 2"
 

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,997
Messages
2,570,239
Members
46,827
Latest member
DMUK_Beginner

Latest Threads

Top