On Mar 6, 6:16 pm, "Wayne Shu" <Wayne...@gmail.comwrote:
Quote:
Hi, guys
>
I am reading Vandevoorde and Josuttis 's "C++ Template The Complete
Guide" these days.
>
When I read the chapter 15: Traits and Policy classes.
>
I copy the code in 15.2.2 that use to determining the class type.
>
The code is below:
#include <iostream>
>
template<typename T>
class IsClassT {
private:
typedef char One;
typedef struct { char a[2]; } Two;
template<typename Cstatic One test(int C::*);
template<typename Cstatic Two test(...);
public:
enum { Yes = sizeof(IsClassT<T>::test<T>(0)) == 1 };
enum { No = !Yes };
>
};
>
struct MyStruct{};
union MyUnion{};
>
int main()
{
std::cout << IsClassT<MyStruct>::Yes << std::endl
<< IsClassT<MyUnion>::Yes << std::endl;
return 0;
>
}
>
It can be compiled using the Comeau C/C++ 4.3.8 for ONLINE_EVALUATION
but it can't be compiled using the MS VC 8 and gcc version 3.4.2
(mingw-special)
the error message is:
1>d:\code\vc8_debug\sample\main.cpp(56) : error C2783:
'IsClassT<T>::Two IsClassT<T>::test(...)' : could not deduce template
argument for 'C'
1 with
1 [
1 T=MyStruct
1 ]
1 d:\code\vc8_debug\sample\main.cpp(54) : see declaration of
'IsClassT<T>::test'
1 with
1 [
1 T=MyStruct
1 ]
1 d:\code\vc8_debug\sample\main.cpp(65) : see reference to
class template instantiation 'IsClassT<T>' being compiled
1 with
1 [
1 T=MyStruct
1 ]
1>d:\code\vc8_debug\sample\main.cpp(56) : error C2784:
'IsClassT<T>::One IsClassT<T>::test(int C::* )' : could not deduce
template argument for 'int C::* ' from 'int'
1 with
1 [
1 T=MyStruct
1 ]
1 d:\code\vc8_debug\sample\main.cpp(53) : see declaration of
'IsClassT<T>::test'
1 with
1 [
1 T=MyStruct
1 ]
1>d:\code\vc8_debug\sample\main.cpp(56) : error C2056: illegal
expression
1>d:\code\vc8_debug\sample\main.cpp(56) : error C2783:
'IsClassT<T>::Two IsClassT<T>::test(...)' : could not deduce template
argument for 'C'
1 with
1 [
1 T=MyUnion
1 ]
1 d:\code\vc8_debug\sample\main.cpp(54) : see declaration of
'IsClassT<T>::test'
1 with
1 [
1 T=MyUnion
1 ]
1 d:\code\vc8_debug\sample\main.cpp(66) : see reference to
class template instantiation 'IsClassT<T>' being compiled
1 with
1 [
1 T=MyUnion
1 ]
1>d:\code\vc8_debug\sample\main.cpp(56) : error C2784:
'IsClassT<T>::One IsClassT<T>::test(int C::* )' : could not deduce
template argument for 'int C::* ' from 'int'
1 with
1 [
1 T=MyUnion
1 ]
1 d:\code\vc8_debug\sample\main.cpp(53) : see declaration of
'IsClassT<T>::test'
1 with
1 [
1 T=MyUnion
1 ]
1>d:\code\vc8_debug\sample\main.cpp(56) : error C2056: illegal
expression
1>Build log was saved at "file://d:\code\vc8_debug\sample\Debug
\BuildLog.htm"
1>sample - 6 error(s), 0 warning(s)
>
Why it can't be compiled using vc8 and gcc??
For me the code looks with some strange logic.
C2783 error is because of the compiler cannot determine a template
argument.
AFAIK, enumerations are defined at compile time and also sizeof of
operator is valid only at compile time. not at runtime.
sizeof(fxn(0));
the above statement is neither making a function call nor validating
the size of return value. I dont know why sizeof returns '0' in this
case, but in the case of an empty class or structure, sizeof operator
returns 1 to avoid some unexpecte behavior that can be occured because
of returning size as 0. e.g is if we are declaring an array of empty
class, it should not be 0 right?
To verify that sizeof(fxn(0)); not making a function call, just
declare the function without defining its body. The linker will not
throw any linker error (even with your code if we make it compilable)
because the function call not happening anywhere. From this we can
veryfiy that there's nothing happening with such type of expression.
even if you define the body it will not be called.
There's another great example from Effective C++ that "Never re-define
the default paramemeter of a virtual funciton in the derived class.
e.g
class Base
{
public:
virtual void Test(COLOR c = RED); // Assume RED nad GREEN are
enumerations
};
class Derived: public Base
{
public:
void Test(COLOR c = GREEN)
}
What's the error in the above code is that you are creating a an
derived class object using base class pointer,
Base* p = new Derived;
p->Test();
when the compiler see the above, code it will replace the deafult
parameter with base class's value since the parameter defaulting is
doing at compiler time. this can cause some unexpected result.
So always differentiate between compile time and runtime operators.