Whole Tomato Software Forums
Whole Tomato Software Forums
Main Site | Profile | Register | Active Topics | Members | Search | FAQ
User name:
Password:
Save Password
Forgot your password?

 All Forums
 Visual Assist
 Feature Requests
 Exclusion list for . -> expansion / correction
 New Topic  Reply to Topic
 Printer Friendly
Author Previous Topic Topic Next Topic  

Mordachai
Tomato Guru

USA
224 Posts

Posted - Oct 15 2012 :  2:29:26 PM  Show Profile  Reply with Quote
I sometimes write wrappers for pointer-types. e.g. FILE*. or HANDLE types, which are ostensibly defined as pointers, but aren't really pointers (and with FILE*, it's not intended to be dereferenced by the programmer).

So... if I could have an exclusionary list for VAX to say "these are not really pointers, PLEASE do NOT replace . operator with -> operator".

I have to hit BS a hundred times a day, and if I forget immediately, then I have to BS twice, type . again, and again remember to hit BS to undo the !@#$!@#$ replacement AGAIN.

(Sigh... frustrating after a few hours) [!]

As always, VAX is an awesome product - love using it overall.

Edited by - Mordachai on Oct 15 2012 2:30:44 PM

accord
Whole Tomato Software

United Kingdom
3287 Posts

Posted - Oct 15 2012 :  10:19:18 PM  Show Profile  Reply with Quote
Can you please post an example code snippet about how you ostensibly define as pointers, and a usage of this object in her guise? You know where the not welcomed correction happens.
So I can see clearly what is happening. Thanks.

Edited by - accord on Oct 15 2012 10:20:42 PM
Go to Top of Page

Mordachai
Tomato Guru

USA
224 Posts

Posted - Oct 16 2012 :  08:14:43 AM  Show Profile  Reply with Quote
FilePointer holds a FileWrapper, which is a wrapper/shim for a FILE* which implements some RAII policy (currently either close or flush on destruction). FilePointer is used to hide the policy, and give an opaque interface for all consumers of a file stream.

The main thing seems to be that I've defined an operator->() (necessary because of how the C run-time library is written).

	class FilePointer
	{
		FilePointer() : m_pFileWrapper(nullptr) { }
		FilePointer(FileWrapper * pfw) : m_pFileWrapper(pfw) { }
		FilePointer(const FilePointer & rhs) : m_pFileWrapper(rhs.m_pFileWrapper), m_references(rhs.m_references) { }

		// accessors
		operator FILE* () { return *m_pFileWrapper; }			// allow rewind(fp), etc. !WARNING! This is the operator that allows for much mischief!
		FILE* operator -> () { return *m_pFileWrapper; }		// allow the C run-time library macros to work
		FILE* get() const { return *m_pFileWrapper; }			// explicit access

		// comparisons
		bool operator == (const FilePointer & rhs) const { return m_pFileWrapper == rhs.m_pFileWrapper; }
		bool operator == (FILE* fp) const { return fp == *m_pFileWrapper; }
		bool operator != (const FilePointer & rhs) const { return m_pFileWrapper != rhs.m_pFileWrapper; }
		bool operator != (FILE* fp) const { return fp != *m_pFileWrapper; }

		//////////////////////////////////////////////////////////////////////////
		// Binary object I/O

		// reads a single item of type T from our stream
		template <typename T>
		void read(T & thing)
		{
			// don't allow us to generate a 'read pointer' function!
			BOOST_STATIC_ASSERT(!(boost::is_pointer<T>::value));

			if (!fread(get(), thing))
				throw IOError(__FUNCTION__);
		}

		// reads in a single item of type T from our stream as a return value (e.g. char c = read<char>())
		template <typename T> T read() { T thing; read(thing); return thing; }

		// write object
		template <typename T>
		void write(T const & thing)
		{
			// don't allow us to generate a 'write out a pointer' function!
			BOOST_STATIC_ASSERT(!(boost::is_pointer<T>::value));

			// write out the binary of thing
			if (!fwrite(get(), thing))
				throw IOError(__FUNCTION__);
		}
	protected:

		FileWrapper *	m_pFileWrapper;	// pointer to FILE* wrapper
		ReferenceCount	m_references;	// reference count
	};

	class FileWrapper
	{
	public:
		// access the raw FILE*
		FILE* get() const { return this ? m_fp : nullptr; }
		operator FILE* () { return this ? m_fp : nullptr; }

		// relinquish ownership of our FILE*
		FILE* release()
		{
			TRACE_FILE_WRAPPER("%s[%p] releasing %X\\n", typeid(*this).name(), this, m_fp);
			FILE* fp = m_fp;
			m_fp = NULL;
			return fp;
		}

		// explicitly close the file
		virtual int close()
		{
			// fclose() docs indicate that closing a NULL stream
			// results in the invalid parameter handler being called
			// so we simply indicate success if no file handle is assigned to us
			if (!m_fp)
				return 0;	

			// execute the actual close
			const int error = ::fclose(m_fp);
			TRACE_FILE_WRAPPER("%s[%p] closed %X (status = %d)\\n", typeid(*this).name(), this, m_fp, error);

			// nullify ourself only if we succeeded in closing the file stream
			if (!error)
				m_fp = NULL;

			return error;
		}

		// destructor (polymorphic to allow subclasses to terminate properly)
		virtual ~FileWrapper() 
		{
			TRACE_FILE_WRAPPER("%s[%p] deleted\\n", typeid(*this).name(), this);
		}

	protected:
		// force only subclasses to really be used by hiding the ctor

		// constructor
		FileWrapper(FILE* fp) : m_fp(fp)
		{
			TRACE_FILE_WRAPPER("%s[%p] created %X\\n", typeid(*this).name(), this, m_fp);
		}

		// disallow copy ctor and assignment
		FileWrapper(const FileWrapper &);
		FileWrapper & operator = (const FileWrapper &);

		// the underlying file
		FILE*	m_fp;
	};


Is this enough information?

I am only realizing that the dereference "correction" only occurs because I have included an operator->(), and NOT because it is a type of FILE*, which I had forgotten (this class has evolved over the years).

So, I guess my suggestion is: Can I tell VAX to NOT assume I mean -> when I type . for this and other classes like it?

Edited by - Mordachai on Oct 16 2012 08:19:30 AM
Go to Top of Page

Mordachai
Tomato Guru

USA
224 Posts

Posted - Oct 16 2012 :  09:52:50 AM  Show Profile  Reply with Quote
Please note that for other smart pointer esq classes I would want the auto-correction. So I don't think that VAX can be smart enough to know which I mean, without help.

The help I'm suggesting is a simple "exclusion" list or some such. Of course, simple is in the eye of the beholder! ;)
Go to Top of Page

feline
Whole Tomato Software

United Kingdom
19014 Posts

Posted - Oct 16 2012 :  3:29:28 PM  Show Profile  Reply with Quote
Thank you for the clear sample code. Assuming you are able to edit the FilePointer class, I think I have a solution for you, this is working here.

Instead of trying to add an exclusion list, it is possible to hide the operator->() member function from VA.

In the FilePointer class I have replaced the operator->() function with the slightly messy code:

//	FILE* operator -> () { return *m_pFileWrapper; }		// allow the C run-time library macros to work
	// work around to hide operator function from Visual Assist X
#define VA_INVISIBLE_OPERATOR_OVERLOAD FILE* operator -> () { return *m_pFileWrapper; }
	VA_INVISIBLE_OPERATOR_OVERLOAD

which will compile to the same thing.

Next create a new file called "va_stdafx.h", place it into the same directory as your .SLN or .VCPROJ file, and add the single line:

#define VA_INVISIBLE_OPERATOR_OVERLOAD

make sure this "va_stdafx.h" file ends with a blank line. Do Not add this file to your solution.

Now press the button:

VA Options -> Performance -> Rebuild symbol databases

and restart your IDE. The va_stdafx.h file is explained here:

http://docs.wholetomato.com?W302

basically I am hiding this macro from our parser, so hiding this member function from our parser, while keeping it in your code. What happens when you try this?

zen is the art of being at one with the two'ness
Go to Top of Page

Mordachai
Tomato Guru

USA
224 Posts

Posted - Oct 17 2012 :  08:46:42 AM  Show Profile  Reply with Quote
Wow - that looks like a solution to me. :)

I'll give it a shot & report back.
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
 Printer Friendly
Jump To:
© 2023 Whole Tomato Software, LLC Go To Top Of Page
Snitz Forums 2000