Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > C++0x "auto" equivalence in non-0x? (function needs to return undeterminedtype value)

Reply
Thread Tools

C++0x "auto" equivalence in non-0x? (function needs to return undeterminedtype value)

 
 
Qi
Guest
Posts: n/a
 
      05-06-2011
What I want to do is,

template <typename T>
void process(const T & value);

UndeterminedType generate();

"generate" may return value in various types, which is unknown when it's
called. What's determined is that all types are already known and
defined.
So I know "generate" can return a value in type A, B or C, but I don't
know which one it exactly is.

The result from "generate" is only used to feed "process", I don't need
to store it. But it will be good if I can store it.

Seems "auto" keyword in C++0x is introduced to solve that problem.

My question is, how to do the equivalence in non-0x C++?

The reason I won't use 0x is seems current compilers can't support it
well. VC only supports "auto" from version 10 while I'm using 9!


--
WQ
 
Reply With Quote
 
 
 
 
m0shbear
Guest
Posts: n/a
 
      05-06-2011
On May 5, 10:56*pm, Qi <(E-Mail Removed)> wrote:
> What I want to do is,
>
> template <typename T>
> void process(const T & value);
>
> UndeterminedType generate();
>
> "generate" may return value in various types, which is unknown when it's
> called. What's determined is that all types are already known and
> defined.
> So I know "generate" can return a value in type A, B or C, but I don't
> know which one it exactly is.
>
> The result from "generate" is only used to feed "process", I don't need
> to store it. But it will be good if I can store it.
>
> Seems "auto" keyword in C++0x is introduced to solve that problem.
>
> My question is, how to do the equivalence in non-0x C++?
>
> The reason I won't use 0x is seems current compilers can't support it
> well. VC only supports "auto" from version 10 while I'm using 9!
>
> --
> WQ


Why not make generate a template function and call generate<T>(...)?
 
Reply With Quote
 
 
 
 
Qi
Guest
Posts: n/a
 
      05-06-2011
On 2011-5-6 11:18, m0shbear wrote:

> Why not make generate a template function and call generate<T>(...)?


Because T is undetermined when calling "generate".
Your that kind of template function needs T to be determined.


--
WQ
 
Reply With Quote
 
Joshua Maurice
Guest
Posts: n/a
 
      05-06-2011
On May 5, 8:25*pm, Qi <(E-Mail Removed)> wrote:
> On 2011-5-6 11:18, m0shbear wrote:
>
> > Why not make generate a template function and call generate<T>(...)?

>
> Because T is undetermined when calling "generate".
> Your that kind of template function needs T to be determined.


This can be a very hard problem to solve. I've looked through the
large and hacky codebase in boost that tries to support pseudo-lambda
functions with its _1, _2, and _3. This is an impossible problem to
solve in all cases, a pain in the ass for suitably general cases, and
maybe doable for easy cases. I would need to know specific details to
offer further advice, though I would suggest reworking it so you don't
have this requirement if at all reasonable.
 
Reply With Quote
 
Qi
Guest
Posts: n/a
 
      05-06-2011
On 2011-5-6 13:15, Joshua Maurice wrote:

> This can be a very hard problem to solve. I've looked through the
> large and hacky codebase in boost that tries to support pseudo-lambda
> functions with its _1, _2, and _3. This is an impossible problem to
> solve in all cases, a pain in the ass for suitably general cases, and
> maybe doable for easy cases. I would need to know specific details to
> offer further advice, though I would suggest reworking it so you don't
> have this requirement if at all reasonable.


Yes, if there is no solution, I will change my design, not very
difficult but it will be a little ugly.

Don't know what details you need.
I would give some pseudo code to explain more.

struct A { void run() const; };
struct B { void run() const; };
struct C { void run() const; };

template <typename T>
void process(const T & value);
{
value.run();
}

/*****************************
How to deal with SomeType?
In C++0x, it can be "auto" (hope I'm correct,
I never tried 0x though),
But how to do it in non-0x?
*****************************/
SomeType generate()
{
switch(random number) {
case 0:
return A();

case 1:
return B();

default:
return C();
}
}

void main()
{
process(generate()); // here is how I want to use "generate"
}

--
WQ
 
Reply With Quote
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      05-06-2011
Qi wrote:

> What I want to do is,
>
> template <typename T>
> void process(const T & value);
>
> UndeterminedType generate();
>
> "generate" may return value in various types, which is unknown when it's
> called. What's determined is that all types are already known and
> defined.
> So I know "generate" can return a value in type A, B or C, but I don't
> know which one it exactly is.
>
> The result from "generate" is only used to feed "process", I don't need
> to store it. But it will be good if I can store it.
>
> Seems "auto" keyword in C++0x is introduced to solve that problem.


I thought, the "auto" keyword will still require that the compiler can
deduce the type at compile time.

> My question is, how to do the equivalence in non-0x C++?
>
> The reason I won't use 0x is seems current compilers can't support it
> well. VC only supports "auto" from version 10 while I'm using 9!



Best,

Kai-Uwe Bux
 
Reply With Quote
 
SG
Guest
Posts: n/a
 
      05-06-2011
On 6 Mai, 07:50, Qi wrote:
>
> /*****************************
> How to deal with SomeType?
> In C++0x, it can be "auto" (hope I'm correct,
> I never tried 0x though),
> But how to do it in non-0x?
> *****************************/
> SomeType generate()
> {
> * *switch(random number) {
> * * *case 0:
> * * * * * return A();
>
> * * *case 1:
> * * * * * return B();
>
> * * *default:
> * * * * * return C();
> * *}
> }


It seems you misunderstood 'auto'. There is nothing dynamic about
'auto'. For functions, 'auto' is part of the new function declaration
syntax:

double foo(int,string); // old syntax (still valid)
auto foo(int,string) -> double; // new syntax

The only difference is that the return type is mentioned last in the
declaration.

> void main()
> {
> * *process(generate()); // here is how I want to use "generate"
> }


This cannot work, neither in C++0x nor in C++98. generate must have
some return type known at compile time. You want to change the type at
runtime. But template argument deduction happens at compile-time. So,
you would need some kind of type-erasing wrapper (boost::variant) and
manually perform some kind of dispatch to select the correct process
function. You can't magically use a runtime type information to select
the right process function at compile-time.

SG
 
Reply With Quote
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      05-06-2011
Qi wrote:

> On 2011-5-6 13:15, Joshua Maurice wrote:
>
>> This can be a very hard problem to solve. I've looked through the
>> large and hacky codebase in boost that tries to support pseudo-lambda
>> functions with its _1, _2, and _3. This is an impossible problem to
>> solve in all cases, a pain in the ass for suitably general cases, and
>> maybe doable for easy cases. I would need to know specific details to
>> offer further advice, though I would suggest reworking it so you don't
>> have this requirement if at all reasonable.

>
> Yes, if there is no solution, I will change my design, not very
> difficult but it will be a little ugly.
>
> Don't know what details you need.
> I would give some pseudo code to explain more.
>
> struct A { void run() const; };
> struct B { void run() const; };
> struct C { void run() const; };
>
> template <typename T>
> void process(const T & value);
> {
> value.run();
> }
>
> /*****************************
> How to deal with SomeType?
> In C++0x, it can be "auto" (hope I'm correct,
> I never tried 0x though),
> But how to do it in non-0x?
> *****************************/
> SomeType generate()
> {
> switch(random number) {
> case 0:
> return A();
>
> case 1:
> return B();
>
> default:
> return C();
> }
> }
>
> void main()
> {
> process(generate()); // here is how I want to use "generate"
> }
>


It seems that the above could be rewritten as:

struct A { void run() const; };
struct B { void run() const; };
struct C { void run() const; };

template <typename T>
void process(const T & value);
{
value.run();
}

void generate()
{
switch(random number) {
case 0: {
A x;
process(x);
}
case 1: {
B x;
process(x);
}
default: {
C x;
process(x);
}
}
}

int main()
{
generate();
}


Alternatively, you could make A, B, C inherit from a common base and make
run() a virtual method. You could also use duck typing: keep A, B, and C
unrelated but provide a class Runnable that can accommodate values of A, B,
and C:

#include <algorithm>
using std::swap;

class Runnable {

struct base {

virtual
~base ( void ) {}

virtual
void run ( void ) {}

virtual
base * clone ( void ) {}

};

template < typename A >
struct derived : base {

A data;

derived ( A const & a )
: data ( a )
{}

virtual
void run ( void ) {
data.run();
}

virtual
derived * clone ( void ) {
return ( new derived ( data ) );
}

};

base * the_ptr;

public:

template < typename A >
Runnable ( A const & a )
: the_ptr( new derived<A>( a ) )
{}

Runnable ( Runnable const & other )
: the_ptr ( other.the_ptr->clone() )
{}

~Runnable ( void ) {
delete ( the_ptr );
}

friend
void swap ( Runnable & lhs, Runnable & rhs ) {
swap( lhs.the_ptr, rhs.the_ptr );
}

Runnable & operator= ( Runnable other ) {
swap( *this, other );
return ( *this );
}

void run ( void ) {
the_ptr->run();
}

};


#include <iostream>
#include <ostream>

struct A {

void run ( void ) {
std::cout << "A\n";
}

};

struct B {

void run ( void ) {
std::cout << "B\n";
}

};

Runnable generate ( int i ) {
if ( i % 2 ) {
return ( A() );
} else {
return ( B() );
}
}

int main ( void ) {
for ( int i = 0; i < 10; ++i ) {
generate(i).run();
}
}


Best,

Kai-Uwe Bux
 
Reply With Quote
 
Qi
Guest
Posts: n/a
 
      05-06-2011
On 2011-5-6 14:54, SG wrote:
>
> This cannot work, neither in C++0x nor in C++98. generate must have
> some return type known at compile time. You want to change the type at
> runtime. But template argument deduction happens at compile-time. So,
> you would need some kind of type-erasing wrapper (boost::variant) and
> manually perform some kind of dispatch to select the correct process
> function. You can't magically use a runtime type information to select
> the right process function at compile-time.


Seems I was confused by the runtime behavior in function "generate".

Now I get it.

I will have to "process" manually for corresponding type.


--
WQ
 
Reply With Quote
 
Qi
Guest
Posts: n/a
 
      05-06-2011
On 2011-5-6 15:00, Kai-Uwe Bux wrote:
>
> Alternatively, you could make A, B, C inherit from a common base and make
> run() a virtual method. You could also use duck typing: keep A, B, and C
> unrelated but provide a class Runnable that can accommodate values of A, B,
> and C:


I would like avoid virtual functions since the processing are quite
cpu intensive.

I would prefer compile time polymorphism over runtime virtual functions.


--
WQ
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Equivalence checking Rick Jackson VHDL 5 11-24-2005 08:38 AM
Equivalence checkers for clocks Forgafun VHDL 1 10-01-2005 03:58 PM
what value does lack of return or empty "return;" return Greenhorn C Programming 15 03-06-2005 08:19 PM
Re: Equivalence checking ALuPin VHDL 1 04-06-2004 06:56 AM
What is the equivalence of ActiveX, COM, COM+ and DCOM in .NET MS News \(MS ILM\) ASP .Net 0 08-28-2003 09:30 AM



Advertisments