Types ambiguity

B

braton

Hello

Consider the following program:


#include <iostream>
#include <string>

class TestClass
{
public:
void f(void) {}
};

template<typename T>
struct F{
typedef void (T::*Type)(void);
};

template<typename T>
void Execute_generic(T) {
std::cout << "Generic function" << std::endl;
}

template<typename T>
void Execute_generic(typename F<T>::Type) {
//void Execute_generic( void (T::*)(void) ) {
std::cout << "Specialization {void (T::*)(void)}" << std::endl;
}

template<typename T>
void Execute_generic(T*) {
std::cout << "Specialization {T*}" << std::endl;
}

template<typename T>
class C {
public:
void fun(T t) { Execute_generic(t); }
};


int main(void)
{
C<std::string> c1;
typedef void (TestClass::*pmem)(void);
C<pmem> c2;
C<double*> c3;
double u=0.0;

c1.fun(std::string("Hello"));
c2.fun(&TestClass::f);
c3.fun(&u);

return 0;
}


When I uncomment the line:
void Execute_generic( void (T::*)(void) )
I got output:

Generic function
Specialization {void (T::*)(void)}
Specialization {T*}

which is what I'm trying to achieve. But when I uncomment the line
that says:
void Execute_generic(typename F<T>::Type)
I got output:
Generic function
Generic function
Specialization {T*}

which I don't understand. What's the difference between void (T::*)
(void) and typename F<T>::Type.
It seems to be the same.

Compiled in Comeau online, MVisual and GCC with pedantic without
warnings.

Thanks for your help
braton
 
B

Barry

When I uncomment the line:
void Execute_generic( void (T::*)(void) )
I got output:

Generic function
Specialization {void (T::*)(void)}
Specialization {T*}

which is what I'm trying to achieve. But when I uncomment the line
that says:
void Execute_generic(typename F<T>::Type)
I got output:
Generic function
Generic function
Specialization {T*}

which I don't understand. What's the difference between void (T::*)
(void) and typename F<T>::Type.
It seems to be the same.

There's nothing different between these two in effect, the former one is
a alias(typedef creates a type alias) of the second one.
Compiled in Comeau online, MVisual and GCC with pedantic without
warnings.

Your compiler is not standard conformed.
 
B

braton

There's nothing different between these two in effect, the former one is
a alias(typedef creates a type alias) of the second one.

Your compiler is not standard conformed.


So according to standard C++ the result of the above-mentioned code
snipped should looks like this:

Generic function
Specialization {void (T::*)(void)}
Specialization {T*}

or there's a reason why I receive the other output when I use
"templated" typedef. It seems strange to me that both Visual C++ and
GCC are not standard conformed but I don't say it's impossible in this
case.

Regards
braton
 
J

James Kanze

Consider the following program:

#include <iostream>
#include <string>

class TestClass
{
public:
void f(void) {}

};

template<typename T>
struct F{
typedef void (T::*Type)(void);

};

template<typename T>
void Execute_generic(T) {
std::cout << "Generic function" << std::endl;

}

template<typename T>
void Execute_generic(typename F<T>::Type) {
//void Execute_generic( void (T::*)(void) ) {
std::cout << "Specialization {void (T::*)(void)}" << std::endl;

}

template<typename T>
void Execute_generic(T*) {
std::cout << "Specialization {T*}" << std::endl;

}

template<typename T>
class C {
public:
void fun(T t) { Execute_generic(t); }

};

int main(void)
{
C<std::string> c1;
typedef void (TestClass::*pmem)(void);
C<pmem> c2;
C<double*> c3;
double u=0.0;

c1.fun(std::string("Hello"));
c2.fun(&TestClass::f);
c3.fun(&u);

return 0;

}

When I uncomment the line:
void Execute_generic( void (T::*)(void) )
I got output:
Generic function
Specialization {void (T::*)(void)}
Specialization {T*}
which is what I'm trying to achieve. But when I uncomment the line
that says:
void Execute_generic(typename F<T>::Type)
I got output:
Generic function
Generic function
Specialization {T*}
which I don't understand. What's the difference between void (T::*)
(void) and typename F<T>::Type.
It seems to be the same.

typename F<T>::Type is an non-deduced context. The compiler
cannot use it to deduce T. (There is a very simple technical
reason for this. What the compiler knows when it tries to do
type deduction here is the type it needs for F<T>::Type. The
only way it can find this type, however, is by generating all
possible instantiations of F<T> until it finds one with a Type
that matches. Since the number of possible instantiations is
infinite, the problem is unsolvable.)
 
J

James Kanze

I disagree.
So according to standard C++ the result of the above-mentioned
code snipped should looks like this:
Generic function
Specialization {void (T::*)(void)}
Specialization {T*}

No. As you presented it, there is no way for the compiler to do
type deduction for the second case, so it ends up using the
more generic form.
or there's a reason why I receive the other output when I use
"templated" typedef. It seems strange to me that both Visual
C++ and GCC are not standard conformed but I don't say it's
impossible in this case.

I know a couple of cases where both VC++ and g++ have the same
bug, but this isn't one of them.
 
B

braton

typename F said:
cannot use it to deduce T. (There is a very simple technical
reason for this. What the compiler knows when it tries to do
type deduction here is the type it needs for F<T>::Type. The
only way it can find this type, however, is by generating all
possible instantiations of F<T> until it finds one with a Type
that matches. Since the number of possible instantiations is
infinite, the problem is unsolvable.)

Thanks for clarification, I see it now.

Regards
braton
 

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,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top