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

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

P: n/a
=========================================
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:al****@connect.to
http://www.simtel.net/pub/oth/19088.html
http://sourceforge.net/users/alexvn
==========================================


Jul 19 '05 #1
Share this Question
Share on Google+
2 Replies


P: n/a
"Alex Vinokur" <al****@bigfoot.com> wrote...
[.. 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
Jul 19 '05 #2

P: n/a

"Victor Bazarov" <v.********@attAbi.com> wrote in message news:vh************@corp.supernews.com...
"Alex Vinokur" <al****@bigfoot.com> wrote...
[.. 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.

Victor


=======================================
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/groups?selm...nnrp1.deja.com

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:al****@connect.to
http://mathforum.org/library/view/10978.html
=====================================


Jul 19 '05 #3

This discussion thread is closed

Replies have been disabled for this discussion.