"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
=====================================