Template virtual member method is not allowed. How to bypass that?

A

Alex Vinokur

=========================================
Windows 2000
CYGWIN_NT-5.0 1.3.22(0.78/3/2)
GNU gcc version 3.2 20020927 (prerelease)
=========================================


Here is some program which is compiled and works fine.

############################################
====== C++ code : File t1.cpp : BEGIN ======
#include <iostream>
using namespace std;

class BBB
{
public :
void foo1 (int n);

protected :
virtual void foo2(int n) = 0;
};

class DDD : public BBB
{
public :
void foo2(int n);
};

void BBB::foo1 (int n)
{
cout << __PRETTY_FUNCTION__ << " : n = " << n << endl;
foo2(n);
}

void DDD::foo2 (int n)
{
cout << __PRETTY_FUNCTION__ << " : n = " << n << endl;
}


int main ()
{
DDD d;
d.foo1(123);
return 0;
}
====== C++ code : File t1.cpp : END ========


====== Compilation & Run : BEGIN ======

$ g++ t1.cpp

void BBB::foo1(int) : n = 123
virtual void DDD::foo2(int) : n = 123

====== Compilation & Run : END ========



I need something like with template virtual member method.
But template virtual member method is not allowed.

############################################
====== C++ code : File t2.cpp : BEGIN ======

#include <iostream>
using namespace std;

class BBB
{
public :
template <typename T>
void foo1 (const T& t);

protected :
template <typename T>
virtual void foo2(const T& t) = 0; // (Line#12) ILLEGAL because template virtual member method is not allowed
};

class DDD : public BBB
{
public :
template <typename T>
void foo2(const T& t);
};

template <typename T>
void BBB::foo1 (const T& t)
{
cout << __PRETTY_FUNCTION__ << " : t = " << t << endl;
foo2(t);
}

template <typename T>
void DDD::foo2 (const T& t)
{
cout << __PRETTY_FUNCTION__ << " : t = " << t << endl;
}


int main ()
{
DDD d;
d.foo1(123);
return 0;
}

====== C++ code : File t2.cpp : END ========


====== Compilation : BEGIN ======

$ g++ t2.cpp

t2.cpp:12: invalid use of `virtual' in template declaration of `virtual void
BBB::foo2(const T&)'

====== Compilation : END ========


Question.
Is there any bypass to get what I want to ?


Thanks,

==========================================
Alex Vinokur
mailto:[email protected]
http://www.simtel.net/pub/oth/19088.html
http://sourceforge.net/users/alexvn
==========================================
 
V

Victor Bazarov

Alex Vinokur said:
[.. example of polymorphism in its simplest use..]
I need something like with template virtual member method.

Why do you think you need that?
But template virtual member method is not allowed.

No, it's not. That's correct.
############################################
====== C++ code : File t2.cpp : BEGIN ======

#include <iostream>
using namespace std;

class BBB
{
public :
template <typename T>
void foo1 (const T& t);

protected :
template <typename T>
virtual void foo2(const T& t) = 0; // (Line#12) ILLEGAL because
template virtual member method is not allowed

Yes. You probably want to make the entire class a template,
or have a nested [helper] class, which should be a template.
Template classes can have virtual functions.
};
[...]

Question.
Is there any bypass to get what I want to ?

No, there is no "bypass" of what is disallowed. But there are
other ways. If you could just tell us what you need that for,
perhaps we could suggest a solution. Try not to phrase your
inquiries "the language doesn't let me do this, how do I do this?"

Victor
 
A

Alex Vinokur

Victor Bazarov said:
Alex Vinokur said:
[.. example of polymorphism in its simplest use..]
I need something like with template virtual member method.

Why do you think you need that?
But template virtual member method is not allowed.

No, it's not. That's correct.
############################################
====== C++ code : File t2.cpp : BEGIN ======

#include <iostream>
using namespace std;

class BBB
{
public :
template <typename T>
void foo1 (const T& t);

protected :
template <typename T>
virtual void foo2(const T& t) = 0; // (Line#12) ILLEGAL because
template virtual member method is not allowed

Yes. You probably want to make the entire class a template,
or have a nested [helper] class, which should be a template.
Template classes can have virtual functions.
};
[...]

Question.
Is there any bypass to get what I want to ?

No, there is no "bypass" of what is disallowed. But there are other ways.

One of such ways are proposed below.
Of course, this approach doesn't solve the problem of disallowance of template virtual member method.
Perhaps it will be useful in certain situations.
If you could just tell us what you need that for,
perhaps we could suggest a solution. Try not to phrase your
inquiries "the language doesn't let me do this, how do I do this?"

You are right. The wording is ambiguous.

=======================================
GNU g++ version 3.3.1 (cygming special)
=======================================


========= C++ code : File t.cpp : BEGIN =========
#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <map>
#include <typeinfo>
#include <assert.h>
using namespace std;

#ifdef __GNUC__
#define FUNC_NAME __PRETTY_FUNCTION__
#else
#define FUNC_NAME ""
#endif

#define COUT \
cout << "[ " \
<< __FILE__ \
<< ", #" \
<< setw(3) \
<< std::right \
<< __LINE__ \
<< " ] " \
<< FUNC_NAME \
<< " : "


// ---------------------
// ---------------------
template <class To, class From>
bool stream_cast (const From& from, To& to)
{
stringstream stream;
stream << from;
return (stream >> to);
}


// ---------------------
struct AuxTypenames
{
friend bool operator< (const AuxTypenames& ins1_i, const AuxTypenames& ins2_i);

string class_typename_;
string arg_typename_;

AuxTypenames (
const string& class_typename_i,
const string& arg_typename_i
)
:
class_typename_ (class_typename_i),
arg_typename_ (arg_typename_i)
{}
};

// ---------------------
bool operator< (const AuxTypenames& ins1_i, const AuxTypenames& ins2_i)
{
if (ins1_i.class_typename_ < ins2_i.class_typename_) return true;
if (ins1_i.class_typename_ > ins2_i.class_typename_) return false;

return (ins1_i.arg_typename_ < ins2_i.arg_typename_);
}



// ---------------------
// ---------------------
class Boo;


// ---------------------
class AuxBaseCaller
{
public :
virtual bool caller(Boo* ptr_io, const string& str_i) = 0;
};


template <typename T1, typename T2>
class AuxCaller : public AuxBaseCaller
{
public :
bool caller(Boo* ptr_io, const string& str_i);
};



// ---------------------
template <typename T1, typename T2>
bool AuxCaller<T1, T2>::caller(Boo* ptr_io, const string& str_i)
{
T2 data;

if (!stream_cast (str_i, data))
{
COUT << "Unable to do stream_cast : "
<< typeid(str_i).name()
<< " to "
<< typeid(data).name()
<< "; From-string-value = <"
<< str_i
<< ">"
<< endl;

return false;
}

T1* ptr = dynamic_cast<T1*> (ptr_io);
assert (!(ptr == NULL));

ptr->foo2 (data);

return true;
}


// ---------------------
// ---------------------
class Boo
{
protected :
void bridge (const string& arg_typename_i, const string& str_i);

public :
static map<AuxTypenames, AuxBaseCaller*> callers_s;

virtual ~Boo () {}

template <typename T>
void foo1 (const T& t);

};

// ---------------------
class Dxx : public Boo
{
template <typename T1, typename T2> friend class AuxCaller;

private :
template <typename T>
void foo2(const T& t) { COUT << "t = " << t << endl; }
};


// ---------------------
class Dyy : public Boo
{
template <typename T1, typename T2> friend class AuxCaller;

private :
template <typename T>
void foo2(const T& t) { COUT << "t = " << t << endl; }
};


// ---------------------
class Dzz : public Boo
{
template <typename T1, typename T2> friend class AuxCaller;

private :
template <typename T>
void foo2(const T& t) { COUT << "t = " << t << endl; }
};



// ---------------------
// ---------------------
template <typename T>
void Boo::foo1 (const T& data_i)
{
COUT << "data_i = " << data_i << endl;

string str;
if (!stream_cast (data_i, str))
{
COUT << "Unable to do stream_cast : "
<< typeid(data_i).name()
<< " to "
<< typeid(str).name()
<< "; From-T-value = <"
<< data_i
<< ">"
<< endl;

return;
}

bridge(typeid(data_i).name(), str);
}


// ---------------------
void Boo::bridge (const string& arg_typename_i, const string& str_i)
{
COUT << "arg_typename_i = " << arg_typename_i << endl;

assert (!callers_s.empty());
const string class_typename (typeid(*this).name());
const map<AuxTypenames, AuxBaseCaller*>::const_iterator find_iter = callers_s.find (AuxTypenames (class_typename, arg_typename_i));

if (find_iter == callers_s.end())
{
COUT << ""
<< "Pair (class typename = "
<< class_typename
<< ", arg typename = "
<< arg_typename_i
<< ") is not allowed"
<< endl;
return;
}

assert (find_iter != callers_s.end());

if (!find_iter->second->caller(this, str_i)) assert (0);

}


// ---------------------
// ---------------------
map<AuxTypenames, AuxBaseCaller*> Boo::callers_s;

#define ADD_CALLER(T1, T2) \
Boo::callers_s[AuxTypenames (typeid(T1).name(), typeid(T2).name())] = \
static_cast<AuxBaseCaller*> (new AuxCaller<T1, T2> ())


// ---------------------
int main ()
{
ADD_CALLER (Dxx, int);
ADD_CALLER (Dxx, char);
ADD_CALLER (Dxx, float);

ADD_CALLER (Dyy, int);
ADD_CALLER (Dyy, char);

// ---------------------
Dxx dxx;
cout << endl;
cout << endl;
cout << "\t--- Dxx test ---" << endl;

dxx.foo1(100);
cout << endl;
dxx.foo1(char('a'));
cout << endl;
dxx.foo1(float (3.14));


Dyy dyy;
cout << endl;
cout << endl;
cout << "\t--- Dyy test ---" << endl;

dyy.foo1(200);
cout << endl;
dyy.foo1(char('b'));
cout << endl;
dyy.foo1(float (2.71));


Dzz dzz;
cout << endl;
cout << endl;
cout << "\t--- Dzz test ---" << endl;

dzz.foo1(300);

// -----
return 0;
}

========= C++ code : File t.cpp : END ===========

Two remarks.
1. stream_cast() was discussed by Dietmar Kuehl at
http://groups.google.com/[email protected]

2. To be sure the stream_cast conversion is bijective, one could use functions which detect stream_cast bijectivity
http://groups.google.com/groups?th=8bb967e46c5e3a87



========= Compilation & Run : BEGIN =========

$ g++ t.cpp

$ a

--- Dxx test ---
[ t.cpp, #175 ] void Boo::foo1(const T&) [with T = int] : data_i = 100
[ t.cpp, #199 ] void Boo::bridge(const std::string&, const std::string&) : arg_typename_i = i
[ t.cpp, #143 ] void Dxx::foo2(const T&) [with T = int] : t = 100

[ t.cpp, #175 ] void Boo::foo1(const T&) [with T = char] : data_i = a
[ t.cpp, #199 ] void Boo::bridge(const std::string&, const std::string&) : arg_typename_i = c
[ t.cpp, #143 ] void Dxx::foo2(const T&) [with T = char] : t = a

[ t.cpp, #175 ] void Boo::foo1(const T&) [with T = float] : data_i = 3.14
[ t.cpp, #199 ] void Boo::bridge(const std::string&, const std::string&) : arg_typename_i = f
[ t.cpp, #143 ] void Dxx::foo2(const T&) [with T = float] : t = 3.14


--- Dyy test ---
[ t.cpp, #175 ] void Boo::foo1(const T&) [with T = int] : data_i = 200
[ t.cpp, #199 ] void Boo::bridge(const std::string&, const std::string&) : arg_typename_i = i
[ t.cpp, #154 ] void Dyy::foo2(const T&) [with T = int] : t = 200

[ t.cpp, #175 ] void Boo::foo1(const T&) [with T = char] : data_i = b
[ t.cpp, #199 ] void Boo::bridge(const std::string&, const std::string&) : arg_typename_i = c
[ t.cpp, #154 ] void Dyy::foo2(const T&) [with T = char] : t = b

[ t.cpp, #175 ] void Boo::foo1(const T&) [with T = float] : data_i = 2.71
[ t.cpp, #199 ] void Boo::bridge(const std::string&, const std::string&) : arg_typename_i = f
[ t.cpp, #207 ] void Boo::bridge(const std::string&, const std::string&) : Pair (class typename = 3Dyy, arg typename = f) is not
allowed


--- Dzz test ---
[ t.cpp, #175 ] void Boo::foo1(const T&) [with T = int] : data_i = 300
[ t.cpp, #199 ] void Boo::bridge(const std::string&, const std::string&) : arg_typename_i = i
[ t.cpp, #207 ] void Boo::bridge(const std::string&, const std::string&) : Pair (class typename = 3Dzz, arg typename = i) is not
allowed

========= Compilation & Run : END ===========


=====================================
Alex Vinokur
mailto:[email protected]
http://mathforum.org/library/view/10978.html
=====================================
 

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,954
Messages
2,570,116
Members
46,704
Latest member
BernadineF

Latest Threads

Top