I am please to announce the launch of Sharparena.com, a developer community focused on the .NET framework and the # languages, C#, F# and J#.

This is an English site where you can ask questions about C#, F#, J# and the .NET framework in general, publish articles and stay up to date with news about the development on the .NET framework.

Here are some links:

On the main site you’ll find a series of FAQs about using the site. Consider reading the following for registering and publishing:

See you there!

, , , Hits for this post: 8878 .

It is often that I see people using namespace directives in header files. This is a bad practice maybe not enought explained, so I will try to clarify why one should always avoid this.

When you are using a using directive (such as using namespace std) or using declarations (such as using std::cout) you are bringing into the current namespace (either the global one or a named one) all the entities from the specified namespace (in the case of a using directive) or the entities specified with using declarations. Header files are meant to be included in sources files (usually more that just one source file) and the order of the include statements is most likely different.
If entities (types, functions, constants, etc.) with coliding names are brought into the same translation unit (source file) via different header files then the compiler will trigger errors due to ambiguities.

The following example will demonstrate this aspect. Suppose that you have an own list implementation in a file called mylist.h.

#pragma once 

namespace mycontainers
{
   class list
   {

   };
}

and you make use of this container in a class called foo, but in the header you are using a namespace directive to avoid writing the fully qualified name for list.

#pragma once
#include "mylist.h"

using namespace mycontainers;

class foo
{
   list mylist_;
};

However, a second class, called bar, is using the STL list, and also using a namespace directive.

#pragma once
#include < list >

using namespace std;

class bar
{
   list< int > mylist_;
};

All good as long as you use foo and bar separatelly. But the moment you need to include them both in the same source file (maybe directly, maybe via another headers) errors arise.

#include "foo.h"
#include "bar.h"

int main()
{
   foo f;

   return 0;
}

Here are the errors:

1>d:mariusvc++win32_testbar.h(9) : error C2872: 'list' : ambiguous symbol
1>        could be 'c:program filesmicrosoft visual studio 9.0vcincludelist(95) : std::list'
1>        or       'd:mariusvc++win32_testmylist.h(6) : mycontainers::list'
1>d:mariusvc++win32_testbar.h(9) : error C2872: 'list' : ambiguous symbol
1>        could be 'c:program filesmicrosoft visual studio 9.0vcincludelist(95) : std::list'
1>        or       'd:mariusvc++win32_testmylist.h(6) : mycontainers::list'

Of course, if you switch the order of #includes in you get another error:

1>d:mariusvc++win32_testfoo.h(8) : error C2872: 'list' : ambiguous symbol
1>        could be 'd:mariusvc++win32_testmylist.h(6) : mycontainers::list'
1>        or       'c:program filesmicrosoft visual studio 9.0vcincludelist(95) : std::list'

A second, more hard to spot error is explained by Sutter and Alexandrescu in C++ Coding Standards – 101 Rules, Guidelines, and Best Practices.
When you make use of a using declaration (using std::list), a snapshot of the used entity is taken. All later references to this entity are based on this snapshot. They provide the following example:

// sample 1
namespace A
{
   int f(double);
}

// sample 2
namespace B
{
   using A::f;
   void g();
}

// sample 3
namespace A
{
   int f(int);
}

// sample 4
void B::g()
{
   f(1);
}

When using A::f is encounted, a snapshot of A::f is taken from what was found so far. Only f(double) was declared already, f(int) is found only later.
So though this later overload was a better match for f(1) it would be ignored, because it wasn’t known at the time of the using declaration.

This issue complicates more if each of the first 3 samples were in different files. Then the order of the $include directives in the file that contains the 4th sample would dictate which overload of f() to be used.
And if sample 4 was itself in a header, other that the first 3, the order of the includes would become even more critical.

For these reasons, you should keep in mind never to use namespace directives or declarations in a header file. Instead use the fully qualified name for the types, functions, constants, etc. that you use, and leave the using directives for the source file exclusively.

, , , Hits for this post: 8050 .

I’ve found myself in situations when I spent lots of time debugging because of some variables declared in a base class were written in tens or maybe hundreds of places in the whole hierarchy, across one or multiple projects even. How could you find the right place where the value of such a variable changes? Well, not easy unless you make some changes to the code. In this article I’m going to show how to create a small wrapper to help you there.

But first, some rules of thumb:

  • Don’t make your variables public. This is pretty basic, but I’ve seen experienced people ignoring it; breaking it is a certain cause for maintenance problems.
  • When you have member variables in a base class that can potentially be assigned in many places across the hierarchy make it private, not protected, and provide Get/Set accessors to read and write it. Moreover, prefer to use this accessors in the base class too, instead of accessing it directly. This way you get only one entry point for reading/writing it, so spotting the places where the value changes will be trivial.

If you decide to go with the second rule that I mentioned I can bet you might be tempted to avoid the last advice and write it directly in the base class. Or if you won’t, one of your teammates will. To enforce that, you can use a wrapper class like the one show below.

template < typename T >
class ExplicitWriteVariable
{
	T value_;

	// do not allow assigning values
	T& operator=(const T& val);

public:
	ExplicitWriteVariable()
	{
	}

	explicit ExplicitWriteVariable(const T& val): value_(val)
	{
	}

	bool operator==(const ExplicitWriteVariable< T >& rhv)
	{
		return value_ == rhv.value_;
	}

	bool operator!=(const ExplicitWriteVariable< T >& rhv)
	{
		return value_ != rhv.value_;
	}

	bool operator==(const T& rhv)
	{
		return value_ == rhv;
	}

	bool operator!=(const T& rhv)
	{
		return value_ != rhv;
	}

	// allow assignment of the wrapper objects, and use Set for modifying the wrapper value
	ExplicitWriteVariable< T >& operator=(const ExplicitWriteVariable< T >& rhv)
	{
		if(this != &rhv)
		{
			Set(rhv.value_);
		}
		return *this;
	}

	// operator T is used for getting the wrapped value
	operator T () const
	{
		return value_;
	}

	// this is the only entry point for setting the value of the variable
	void Set(const T& val)
	{
		value_ = val;
	}
};

This template class has the following characteristics:

  • provides a default constructor and an explicit constructor
  • the assignment operator is made private and not implemented, which means you cannot use an object of this type on the left side of an assignment
  • provides the operator T() which allows to read the value without needing an explicit Get accessor
  • provides a Set accessor for changing the wrapper value; this is the only possible entry point for writing
  • has some comparison operators

If you use this to wrap variables in a base class you don’t make it private, but protected in the base class, otherwise you’ll have to provide get/set accessors for the ExplicitWriteVariable object itself. The lacking of operator= will force you though to use the Set() method explicitly.

Here are some samples for using the class:

void Print(int val)
{
	std::cout << val << std::endl;
}

int main()
{
	ExplicitWriteVariable< int > val(10);

	Print(val);
	if(val % 10 == 0) std::cout << "multiple of 10" << std::endl;

	val.Set(43);

	Print(val);
	if(val % 2 == 1) std::cout << "odd number" << std::endl;

	return 0;
}
10
multiple of 10
43
odd number

The following produces an error:

ExplicitWriteVariable< int > val(10);
val = 43; // error C2248

, , , Hits for this post: 7803 .