   typename
  Ive been reading more exceptional C++ by Herb Sutter, and he comments that the following code shouldn't compile due to there not being the keyword *typename* before the dependant types. Yet im running visual studio 2008, and the code that he says is incorrect seems to compile fine for me.Here is the code that he says wont compile// Example 5-2//template<typename T>class X_base{public:typedef T instantiated_type;};template<typename A, typename B>class X : public X_base<B>{public:bool operator()( const instantiated_type& i ) const{return i != instantiated_type();}// ... more stuff ...};Here is his reasoningQuote:The problem with X is that instantiated_type is meant to refer to the typedef supposedlyinherited from the base class X_base. Unfortunately, at the time the compiler parses the inlineddefinition of X<A,B>::operator()(), dependent names (again, names that depend on the templateparameters, such as the inherited X_Base:: instantiated_type) are not visible, and so thecompiler will complain that it doesn't know what instantiated_type is supposed to mean.Dependent names become visible only later, at the point where the template is actually instantiated.If you're wondering why the compiler couldn't just figure it out anyway, pretend that you're a compilerand ask yourself how you would figure out what instantiated_type means here. It's an illuminatingexercise. Bottom line: You can't figure it out because you don't know what B is yet, and whether lateron there might be a specialization for X_base that makes X_base::instantiated_typesomething unexpected—any type name, or even a member variable. In the unspecialized X_basetemplate above, X_base<T>::instantiated_type will always be T, but there's nothing preventingsomeone from changing that when specializing. For example:Here is his corrected code without using typedefs to make it clean// Example 5-2(a)://template<typename A, typename B>class X : public X_base<B>{public:bool operator()(const typename X_base<B>::instantiated_type& i) const{return i != typename X_base<B>::instantiated_type();}// ... more stuff ...};Here is the code i compiled#include <iostream>#include <string>using namespace std;template<typename T>class X_base{public:typedef T instantiated_type;};template<typename A, typename B>class X : public X_base<B>{public:bool operator()( const instantiated_type& i ) const{return i != instantiated_type();}};int main(){X<int, char> x1;if(x1('f')){cout << "Not the same\n";}else cout << "Same";getchar();}And the same goes for the following code. From what i thought i understood about using typename, it is required in the commented out places, yet it compiles fine without it.#include <iostream>#include <string>using namespace std;class A{public:typedef int _IDtype;};template <typename T>void DisplayMember(const T& in){cout << sizeof( /*typename*/ T::_IDtype);/*typename*/ T::_IDtype n;cout << n << "   " << &n;}int main(){A a;DisplayMember<A>(a);getchar();}
  MSVC accepts a lot of template code that isn't actually supposed to be valid. If you tried a different compiler, say gcc, you'd probably find that typename is actually needed in those places.   ;  If you disable "language extensions" in the compiler options, IIRC it will generate an error.   ;Quote:Original post by rip-offIf you disable "language extensions" in the compiler options, IIRC it will generate an error.As of MSVC 2008, even with language extensions disabled, MSVC will still accept large amounts of code with missing typename. I don't know if this will be changed in 2010.   ;  Thanks. I tried as you mentioned by disabling the extensions, but my second example still worked. Why have they done this? it makes it very confusing, surely it should be a feature that you turn on, not turn off.   ;  Basically they did it this way because when MSVC originally implemented templates the language specification wasn't finalized.   