Whole Tomato Software Forums
Whole Tomato Software Forums
Main Site | Profile | Register | Active Topics | Members | Search | FAQ
 All Forums
 Visual Assist
 Technical Support
 Syntax highlighting bug : build 1548

You must be registered to post a reply.
Click here to register.

Screensize:
UserName:
Password:
Format: BoldItalicizeUnderlineStrikethrough Align leftCenterAlign right Insert horizontal ruleUpload and insert imageInsert hyperlinkInsert email addressInsert codeInsert quoted textInsert listInsert Emoji
   
Message:

Forum code is on.
Html is off.

 
Check to subscribe to this topic.
   

T O P I C    R E V I E W
MrDoomMaster Posted - Feb 26 2007 : 3:36:58 PM
Below I'm going to paste a large amount of code. This code contains a class, named ShipyardIterator which is a template class. Inside of this class, as you will see, there's many "typename" keywords spread throughout the file. For example, typename t_type::iterator& iter.

Using the default syntax coloring setup provided by VAX upon a fresh installation, the "iter" keyword in the bolded example above is colored in BLUE. Sometimes, purple (meaning it's getting confused between macros & identifiers or class names). The proper color for the 'iter' keyword should be GRAY.

For a test case, take the entirety of the code I am fixing to paste below and put it in a fresh header file. Open this header file using Visual Studio 2005 Professional (the bug might occur on other IDE's, not sure though.) and ensure you are using the default settings for syntax coloring in Visual Assist. Skim through the document where all of the typename t_type::iterator lines are and look at the color of the corresponding variable. It's definitely bugged!


#ifndef _SHIPYARDITERATOR_HPP_
#define _SHIPYARDITERATOR_HPP_

#include <vector>

#include "PersistedState.hpp"
#include "Shipyard.hpp"


class SkybladeInfo
{
private:
	const Shipyard::Skyblade* m_unpurchased;
	PurchasedShip* m_purchased;

public:
	SkybladeInfo( const Shipyard::Skyblade* unpurchased, PurchasedShip* purchased ) :
		m_unpurchased( unpurchased ),
		m_purchased( purchased )
	{
	}

	friend class Obsoletes;
};

class SkybladeWeaponInfo
{
};


namespace do_not_touch
{
	template< typename t_type >
	class ShipyardIterator
	{
	public:
		enum ClampType
		{
			CLAMP,
			LOOP
		};

	private:
		t_type& m_inventory;
		typename t_type::iterator m_current;
		ClampType m_clampType;

		void AdvanceIterator( typename t_type::iterator& iter, int step )
		{
			// @TODO - RCD
			// Only supports steps of 1 or -1 at the moment
			if( step == 1 || step == -1 )
			{
				switch( m_clampType )
				{
				case CLAMP:
					{
						if( step == 1 )
						{
							if( iter != m_inventory.end() )
							{
								t_type::iterator temp = iter;
								++temp;

								if( temp != m_inventory.end() )
								{
									iter = temp;
								}
							}
						}
						else
						{
							if( iter != m_inventory.begin() )
							{
								--iter;
							}
						}

						break;
					}

					// @TODO - RCD
					// Implement looping
				case LOOP:
					{
						break;
					}
				}
			}
		}

	public:
		ShipyardIterator( t_type& inventory ) :
			m_inventory( inventory ),
			m_clampType( CLAMP )
		{
			m_current = inventory.begin();
		}

		ShipyardIterator( t_type& inventory, typename t_type::iterator& current ) :
			m_inventory( inventory ),
			m_current( current ),
			m_clampType( CLAMP )
		{
		}

		inline void SetClampType( ClampType type )
		{
			m_clampType = type;
		}

		inline typename t_type::value_type& operator*()
		{
			return *m_current;
		}

		inline typename t_type::value_type* operator->()
		{
			return &(*m_current);
		}

		inline const typename t_type::value_type* operator->() const
		{
			return &(*m_current);
		}

		inline ShipyardIterator< t_type >& operator++()
		{
			AdvanceIterator( m_current, 1 );
			return *this;
		}

		inline ShipyardIterator< t_type >& operator--()
		{
			AdvanceIterator( m_current, -1 );
			return *this;
		}
	};
}

typedef std::vector< SkybladeInfo > SkybladeInventory;
typedef std::vector< SkybladeWeaponInfo > SkybladeWeaponInventory;
typedef do_not_touch::ShipyardIterator< SkybladeInventory > SkybladeIterator;
typedef do_not_touch::ShipyardIterator< SkybladeWeaponInventory > SkybladeWeaponIterator;

#endif // _SHIPYARDITERATOR_HPP_
4   L A T E S T    R E P L I E S    (Newest First)
feline Posted - Feb 27 2007 : 1:54:36 PM
*ah* this makes sense, thank you for the explanation.

case=5279
holedigger Posted - Feb 27 2007 : 1:07:19 PM
C++ cannot know if t_type::iterator is a type or not until the template is instantiated. It assumes it is NOT a type unless explicitly told it is. Here's an example from Scott Meyers' "Effective C++" book:

template<typename C>
void print2nd(const C& container)
{
C::const_iterator * x;
}

Either x is a pointer to a C::const_iterator, or instead the statement is a multiplication between two variables. C++ actually assumes the multiplication. To fix it, you need "typename C::const_iterator * x;"
MrDoomMaster Posted - Feb 27 2007 : 12:39:49 PM
quote:
Originally posted by feline

I am seeing odd colouring here, but to be honest I am confused by this code. Just taking a small piece, specifically:

	template< typename t_type >
	class ShipyardIterator
	{
	public:
		enum ClampType	{ CLAMP, LOOP };

	private:
		t_type& m_inventory;
		typename t_type::iterator m_current;

		// *SNIP*
	};


I have reformatted the enum to save space.

I do some template programming, but not a vast amount, so perhaps there is simply something I am not familiar with going on here, but why is "typename" used on the "m_current" line?

You are using "::iterator", which has to be defined on the type that is used to instantiate this template class, but I would expect the compiler to enforce this restriction at compile time, if "::iterator" is not valid, e.g. because you used the type "int" the code will simply not compile.



The template class expects either std::vector or std::list, this is by design. If either of these are not specified as the template parameter to the class, the compiler will generate errors due to the "iterator" type not existing in the template type passed in.

I don't know the formal explanation of the situation, all I can tell you is if you're using a typedef inside of an unknown type, you must specify "typename" so that the compiler knows it's a type. For example:

template< typename T >
class Foo
{
    T::someTypeDefine m_myVar;
};


the compiler will throw an error here because the inner type, "someTypeDefine" is unknown. If you add "typename" in front of this line, the compiler will not throw an error because you've told it that it's unknown. It's a bit weird, but definitely a requirement in my situation.

For more information on the specifics of the "typename" keyword, visit:
http://msdn2.microsoft.com/en-us/library/8y88s595(VS.80).aspx
feline Posted - Feb 27 2007 : 12:23:55 PM
I am seeing odd colouring here, but to be honest I am confused by this code. Just taking a small piece, specifically:

	template< typename t_type >
	class ShipyardIterator
	{
	public:
		enum ClampType	{ CLAMP, LOOP };

	private:
		t_type& m_inventory;
		typename t_type::iterator m_current;

		// *SNIP*
	};


I have reformatted the enum to save space.

I do some template programming, but not a vast amount, so perhaps there is simply something I am not familiar with going on here, but why is "typename" used on the "m_current" line?

You are using "::iterator", which has to be defined on the type that is used to instantiate this template class, but I would expect the compiler to enforce this restriction at compile time, if "::iterator" is not valid, e.g. because you used the type "int" the code will simply not compile.

© 2023 Whole Tomato Software, LLC Go To Top Of Page
Snitz Forums 2000