[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c++

template type only known at runtime

Ralf Goertz

11/18/2008 10:52:00 AM

Hi,

I want to do able to declare an object bar of a templated class foo
where the actual template type of foo is only know at runtime:

-----

#include <string>

template <class T> class foo {
T x;
public:
void do_something_depending_on_type_of_T(){

...
};
}

int main(int argc, char *argv[]) {
if (argc==1) //default type string should be used
foo<std::string> bar;
else //use class int
foo<int> bar;
bar.do_something_depending_on_type_of_T();
return 0;
}

-----

I know it doesn't work like this but is it possible at all?

Ralf

8 Answers

Leandro Melo

11/18/2008 11:20:00 AM

0

On 18 nov, 08:51, Ralf Goertz
<r_goe...@expires-2006-11-30.arcornews.de> wrote:
> Hi,
>
> I want to do able to declare an object bar of a templated class foo
> where the actual template type of foo is only know at runtime:
>
> -----
>
> #include <string>
>
> template <class T> class foo {
>     T x;
> public:
>     void do_something_depending_on_type_of_T(){
>
>         ...
>     };
>
> }
>
> int main(int argc, char *argv[]) {
>     if (argc==1) //default type string should be used
>         foo<std::string> bar;
>     else //use class int
>         foo<int> bar;
>     bar.do_something_depending_on_type_of_T();
>     return 0;
>
> }
>

Template based code is constructed at compile time (static
polymorphism). If you need dynamic polymorphism use virtual functions.
However, your code has a general C++ problem (not specific to
templates). The line bar.do_something_depending_on_type_of_T(); will
generate an error because bar is undefined. This would happen even if
bar was not a template.

I don't know if this is the best design for you. But the closest I can
get to it is through template specialization:

emplate <class T> class foo
{
public:
void do_something()
{} //You don't need trailing semi-colon here.
}; //You need it here though.

template <> class foo<std::string>
{
public:
void do_something()
{ /*Implementation for string */ }
};

template <> class foo<int>
{
public:
void do_something()
{ /*Implementation for int */ }
};

int main(int argc, char *argv[])
{
foo<std::string> stringBar;
foo<int> intBar;
if (argc==1)
stringBar.do_something();
else
intBar.do_something();
return 0;
}

--
Leandro T. C. Melo

maverik

11/18/2008 12:12:00 PM

0

On Nov 18, 1:51 pm, Ralf Goertz
<r_goe...@expires-2006-11-30.arcornews.de> wrote:

> I know it doesn't work like this but is it possible at all?

It wouldn't work even if you solve your problems with templates
because of scoping:

> int main(int argc, char *argv[]) {
> if (argc==1) //default type string should be used
> foo<std::string> bar;
> else //use class int
> foo<int> bar;
> bar.do_something_depending_on_type_of_T();

bar is undefined here (out of scope).

> return 0;
> }

maverik

11/18/2008 12:16:00 PM

0

On Nov 18, 1:51 pm, Ralf Goertz
<r_goe...@expires-2006-11-30.arcornews.de> wrote:
> Hi,
>
> I want to do able to declare an object bar of a templated class foo
> where the actual template type of foo is only know at runtime:

The most painless solution I think looks like:

int main(int argc, char *argv[]) {
    if (argc == 1) {
        foo<std::string> bar;
bar.do_something_depending_on_type_of_T();
} else {
        foo<int> bar;
bar.do_something_depending_on_type_of_T();
}
    return 0;
}

Of course, may be a better solution also exists.

Ralf Goertz

11/18/2008 1:17:00 PM

0

maverik wrote:

> On Nov 18, 1:51 pm, Ralf Goertz
> <r_goe...@expires-2006-11-30.arcornews.de> wrote:
>
>> I know it doesn't work like this but is it possible at all?
>
> It wouldn't work even if you solve your problems with templates
> because of scoping:

I know about the scoping problem. The code was just there to illustrate
what I want which was hard for me to describe in prose. The problem is
similar to one I had a year ago or so. I had wanted to create a
reference to cin or an ifstream object depending on how the program was
invoked. At that time I was wondering why C++ didn't have a deferred
intialization feature for references like

istream &config;
ifstream ifs;
if (config_is_read_from_cin) config=cin; else config=ifs;

It can be done with pointers why not with references. Anyway, it seems I
have to use the apprach you gave in the other posting, thanks, also to
Leandro.

Ralf

Hendrik Schober

11/18/2008 8:45:00 PM

0

Ralf Goertz wrote:
> maverik wrote:
>
>> On Nov 18, 1:51 pm, Ralf Goertz
>> <r_goe...@expires-2006-11-30.arcornews.de> wrote:
>>
>>> I know it doesn't work like this but is it possible at all?
>> It wouldn't work even if you solve your problems with templates
>> because of scoping:
>
> I know about the scoping problem. The code was just there to illustrate
> what I want which was hard for me to describe in prose. The problem is
> similar to one I had a year ago or so. I had wanted to create a
> reference to cin or an ifstream object depending on how the program was
> invoked. At that time I was wondering why C++ didn't have a deferred
> intialization feature for references like
>
> istream &config;
> ifstream ifs;
> if (config_is_read_from_cin) config=cin; else config=ifs;
>
> It can be done with pointers why not with references. [...]

std::istream& is = config_is_read_from_cin ? std::cin : ifs;

> Ralf

Schobi

Hendrik Schober

11/18/2008 8:48:00 PM

0

maverik wrote:
> On Nov 18, 1:51 pm, Ralf Goertz
> <r_goe...@expires-2006-11-30.arcornews.de> wrote:
>> Hi,
>>
>> I want to do able to declare an object bar of a templated class foo
>> where the actual template type of foo is only know at runtime:
>
> The most painless solution I think looks like:
>
> int main(int argc, char *argv[]) {
> if (argc == 1) {
> foo<std::string> bar;
> bar.do_something_depending_on_type_of_T();
> } else {
> foo<int> bar;
> bar.do_something_depending_on_type_of_T();
> }
> return 0;
> }
>
> Of course, may be a better solution also exists.

template< class T >
inline void do_it() {foo<int>().do_something_depending_on_type_of_T();)

int main(int argc, char *argv[]) {
if (argc == 1) {
do_it<std::string>();
} else {
do_it<int>();
}
return 0;
}

Schobi

Hendrik Schober

11/18/2008 8:52:00 PM

0

Ralf Goertz wrote:
> Hi,
>
> I want to do able to declare an object bar of a templated class foo
> where the actual template type of foo is only know at runtime:

If the type is only known at run-time, you need run-time
polymorphy, which is done using virtual functions and
inheritance. However, that doesn't mean you can't use
templates at all:

class foo_base {
public:
virtual void do_something_depending_on_type_of_T() = 0;
};

template< typename T >
class foo : public foo_base {
public:
virtual void do_something_depending_on_type_of_T() {}
};

> [...]
> Ralf

Schobi

Ralf Goertz

11/19/2008 12:16:00 PM

0

Hendrik Schober wrote:

> Ralf Goertz wrote:
>> Hi,
>>
>> I want to do able to declare an object bar of a templated class foo
>> where the actual template type of foo is only know at runtime:
>
> If the type is only known at run-time, you need run-time
> polymorphy, which is done using virtual functions and
> inheritance. However, that doesn't mean you can't use
> templates at all:
>
> class foo_base {
> public: virtual void do_something_depending_on_type_of_T() = 0; };
> virtual void do_something_depending_on_type_of_T() = 0;
> };
>
> template< typename T >
> class foo : public foo_base {
> public:
> virtual void do_something_depending_on_type_of_T() {}
> };


Actually, I just need two different types for the template,
foo<std::string> and foo<int>. The only difference is the id type I get
from a database, it can be either integer or char and is known only at
runtime. If it is numeric I still have to do some calculations with it
(so I can't just sql-cast it to char and use std::string in my program).
Also, the way of writing back the data to the db differs because of
quoting. "id" must be part of the class as I also need it for
std::map<T,double> within class foo. But wrapping it in another template
function as you also suggested seems to be the way to go.

Thanks for the ternary ?: suggestion in the other posting!

Ralf