Connecting Tech Pros Worldwide Forums | Help | Site Map

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

Alex Vinokur
Guest
 
Posts: n/a
#1: Jul 19 '05
=========================================
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:alexvn@connect.to
http://www.simtel.net/pub/oth/19088.html
http://sourceforge.net/users/alexvn
==========================================





Victor Bazarov
Guest
 
Posts: n/a
#2: Jul 19 '05

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


"Alex Vinokur" <alexvn@bigfoot.com> wrote...[color=blue]
> [.. example of polymorphism in its simplest use..][/color]
[color=blue]
> I need something like with template virtual member method.[/color]

Why do you think you need that?
[color=blue]
> But template virtual member method is not allowed.[/color]

No, it's not. That's correct.
[color=blue]
>
> ############################################
> ====== 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[/color]
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.
[color=blue]
> };[/color]

[...]
[color=blue]
> Question.
> Is there any bypass to get what I want to ?[/color]

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


Alex Vinokur
Guest
 
Posts: n/a
#3: Jul 19 '05

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



"Victor Bazarov" <v.Abazarov@attAbi.com> wrote in message news:vh5v3e9hkkqjdf@corp.supernews.com...[color=blue]
> "Alex Vinokur" <alexvn@bigfoot.com> wrote...[color=green]
> > [.. example of polymorphism in its simplest use..][/color]
>[color=green]
> > I need something like with template virtual member method.[/color]
>
> Why do you think you need that?
>[color=green]
> > But template virtual member method is not allowed.[/color]
>
> No, it's not. That's correct.
>[color=green]
> >
> > ############################################
> > ====== 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[/color]
> 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.
>[color=green]
> > };[/color]
>
> [...]
>[color=green]
> > Question.
> > Is there any bypass to get what I want to ?[/color]
>
> No, there is no "bypass" of what is disallowed. But there are other ways.[/color]

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.
[color=blue]
> 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?"[/color]

You are right. The wording is ambiguous.
[color=blue]
>
> Victor
>
>[/color]

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




Closed Thread


Similar C / C++ bytes