universal selector

V

Vladimir

Hello!

I'd like to select one of possible entities according to a given index:

select(index, A, B)

would return A if index is 0, B if index is (or greater than) 1.

so i write:

template<typename T> T select(int index, T a, T b)
{
return (index == 0) ? a : b;
}

this works fine when calling selected function:

select(index, somefunction0, somefunction1)(args...)

but fails for class member functions - what should I do?
Ideally I want it universal, without the need
to rewrite select() for each class.
 
B

Bob Hairgrove

Hello!

I'd like to select one of possible entities according to a given index:

select(index, A, B)

would return A if index is 0, B if index is (or greater than) 1.

so i write:

template<typename T> T select(int index, T a, T b)
{
return (index == 0) ? a : b;
}

this works fine when calling selected function:

select(index, somefunction0, somefunction1)(args...)

but fails for class member functions - what should I do?
Ideally I want it universal, without the need
to rewrite select() for each class.

You cannot call non-static member functions without an object.
 
A

Alf P. Steinbach

* Vladimir:
Hello!

I'd like to select one of possible entities according to a given index:

select(index, A, B)

would return A if index is 0, B if index is (or greater than) 1.

so i write:

template<typename T> T select(int index, T a, T b)
{
return (index == 0) ? a : b;
}

this works fine when calling selected function:

select(index, somefunction0, somefunction1)(args...)

but fails for class member functions - what should I do?
Ideally I want it universal, without the need
to rewrite select() for each class.

#include <iostream>
#include "generalmaker.h"
#include <string>
#include <list>

using namespace std;

#include <iostream>

template<typename T> T select(int index, T a, T b)
{
return (index == 0) ? a : b;
}

class X
{
public:
void a( char const s[] ) const
{
std::cout << "a: " << s << std::endl;
}

void b( char const s[] ) const
{
std::cout << "b: " << s << std::endl;
}
};

int main()
{
X o;

(o.*select( 0, X::a, X::b ))( "Silly syntax, yes." );
}
 
G

Gianni Mariani

Vladimir said:
Hello!

I'd like to select one of possible entities according to a given index:

select(index, A, B)

would return A if index is 0, B if index is (or greater than) 1.

so i write:

template<typename T> T select(int index, T a, T b)
{
return (index == 0) ? a : b;
}

this works fine when calling selected function:

select(index, somefunction0, somefunction1)(args...)

but fails for class member functions - what should I do?
Ideally I want it universal, without the need
to rewrite select() for each class.

The code below compiled fine. What exactly is your problem ?

template<typename T> T select(int index, T a, T b)
{
return (index == 0) ? a : b;
}

struct X
{
void f1() {}
void f2() {}
};

int main()
{
void (X::*z)() = select( 0, &X::f1, &X::f2 );

X q;

(q.*(select( 1, &X::f1, &X::f2 )))();
(q.*z)();
}
 
P

puppet_sock

Hello!

I'd like to select one of possible entities according to a given index:

select(index, A, B)

would return A if index is 0, B if index is (or greater than) 1.

so i write:

template<typename T> T select(int index, T a, T b)
{
return (index == 0) ? a : b;
}

this works fine when calling selected function:

select(index, somefunction0, somefunction1)(args...)

but fails for class member functions - what should I do?
Ideally I want it universal, without the need
to rewrite select() for each class.

#include <iostream>

template<typename T> T select(int index, T a, T b)
{
return (index == 0) ? a : b;
}

class test
{
int val;
public:
test(int inVal):val(inVal) {}
int testFunc() {return val;}
};


int main(int argc, char* argv[])
{
test one(1);
test two(2);

std::cout << select(0,one.testFunc() ,two.testFunc() ) << std::endl ;

std::cout << select(1,one.testFunc() ,two.testFunc() ) << std::endl ;

return 0;
}

Output
1
2

Ok, I'm not quite getting the problem.
Socks
 
A

Alf P. Steinbach

* (e-mail address removed):
Hello!

I'd like to select one of possible entities according to a given index:

select(index, A, B)

would return A if index is 0, B if index is (or greater than) 1.

so i write:

template<typename T> T select(int index, T a, T b)
{
return (index == 0) ? a : b;
}

this works fine when calling selected function:

select(index, somefunction0, somefunction1)(args...)

but fails for class member functions - what should I do?
Ideally I want it universal, without the need
to rewrite select() for each class.

#include <iostream>

template<typename T> T select(int index, T a, T b)
{
return (index == 0) ? a : b;
}

class test
{
int val;
public:
test(int inVal):val(inVal) {}
int testFunc() {return val;}
};


int main(int argc, char* argv[])
{
test one(1);
test two(2);

std::cout << select(0,one.testFunc() ,two.testFunc() ) << std::endl ;

std::cout << select(1,one.testFunc() ,two.testFunc() ) << std::endl ;

return 0;
}

Output
1
2

Ok, I'm not quite getting the problem.

Each of your select calls makes two function calls for the arguments.

The OP wants just one, namely a call of the selected function.

That's easily achieved, as Gianni Mariani and I have shown earlier.
 
V

Vladimir

Bob Hairgrove said:
You cannot call non-static member functions without an object.

so, why

select(index, obj.somefunction0, obj.somefunction1)(args...)

doesn't work as expected?

Why there is so much difference between functions and
member functions? Aren't templates supposed to be matched
to any type? Is it compiler implementation issue?
 
V

Vladimir

Gianni Mariani said:
The code below compiled fine. What exactly is your problem ?

(q.*(select( 1, &X::f1, &X::f2 )))();

My problem is that we usually write helper functions
to simplify coding and improve readability.
This also means less typing which unfortunately
isn't the case with the above solution. :(

Well this code works, but instead of quickly selecting
and calling member function we have to do scope resolution,
address taking, dereferencing and lots of brackets...
 
B

Bob Hairgrove

so, why

select(index, obj.somefunction0, obj.somefunction1)(args...)

doesn't work as expected?

It's simply the wrong syntax for calling pointer to member. Try this:

(obj.*(select(index, somefunction0, somefunction1)))(args...)
Why there is so much difference between functions and
member functions? Aren't templates supposed to be matched
to any type? Is it compiler implementation issue?

As you can see, everything inside the brackets beginning with
"select(" is just the way you had it. Templates work fine. It's
afterwards where you have trouble. RTFM about pointer to member. They
are actually a kind of offset into the class function list, not real
pointers.

Using an index to select functions seems to me not very
object-oriented. Maybe you could rethink the design and use virtual
functions instead.
 
O

Old Wolf

My problem is that we usually write helper functions
to simplify coding and improve readability.
This also means less typing which unfortunately
isn't the case with the above solution. :(

Well this code works, but instead of quickly selecting
and calling member function we have to do scope resolution,
address taking, dereferencing and lots of brackets...

Then, don't use silly obfuscations like this select() function.
It might save you a couple of characters from time to time but
it makes the code harder to read for anybody who doesn't know
what the function does (or even yourself, if you come back to
it in future and forget what the select criterion was). FWIW
it also collides with the POSIX 'select' function, if you ever
port your code to Unix systems.
 
V

Vladimir

Old said:
Then, don't use silly obfuscations like this select() function.

Why obfuscations? Isn't it nice to get for example
traffic light color this way:

color = select(number, green, yellow, red);

This is done without cumbersome "?:" or switch() statements,
or declaring some data structure in the middle of nowhere :)

It works fine with everything except member functions.
Maybe I should redesign my code. Anyway, here's my task.

I often have 3 similar methods (same arguments) in a class
which calculate a function with different accuracy:

class {
...
double precise(args);
double approx0(args); // zero order approximation
double approx1(args); // first order approximation
};

I have to call them in a loop with other code:

for(int i = 0; i < 3; i++) {
select(i, precise, approx0, approx1)(args);
...
/* lots of other code */
}

so on each iteration appropriate member function should be
called except it doesn't work with simple syntax.
Do I have a wrong approach, or maybe not object-oriented enough?
 
G

Gianni Mariani

Vladimir said:
Why obfuscations? Isn't it nice to get for example
traffic light color this way:

color = select(number, green, yellow, red);

This is done without cumbersome "?:" or switch() statements,
or declaring some data structure in the middle of nowhere :)

It works fine with everything except member functions.
Maybe I should redesign my code. Anyway, here's my task.

I often have 3 similar methods (same arguments) in a class
which calculate a function with different accuracy:

class {
...
double precise(args);
double approx0(args); // zero order approximation
double approx1(args); // first order approximation
};

I have to call them in a loop with other code:

for(int i = 0; i < 3; i++) {
select(i, precise, approx0, approx1)(args);
...
/* lots of other code */
}

so on each iteration appropriate member function should be
called except it doesn't work with simple syntax.
Do I have a wrong approach, or maybe not object-oriented enough?

There is nothing wrong with your approach. The language simply does not
support it quite like you want it to.

I concur that you should use a different name (select is an important
posix function).

If C++ had a "typeof" operator you could do this below. However, this
is not standard (only works with GCC).

template <typename T> struct H {
typedef T type;
};

#define choosefun(A,B,C,D)\
((A).*((B) ? &H<typeof(A)>::type::C : &H<typeof(A)>::type::D))

struct X {
double precise();
double approx0(); // zero order approximation
double approx1(); // first order approximation
};

int main()
{
X x;

choosefun(x,true,approx0,approx1)();
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top