Every so often, I come across code that uses empty structures, like the one above, for all sorts of stuff. In one scenario, I've seen them used as part of a conversion operator.
What possible uses could an empty structure have? Could someone provide and example or two of their use?
In general, it can be used for method colouring. For example, an empty structure to colour the constructor is commonly used in the implementation of the prototype (exemplar) pattern:
Both Method Colouring & Tag Dispatching are foreign terms to me. I found information (including the information you provided) in regards to tag dispatching, but none regarding method colouring. What do you mean by "colouring the constructor"?
Let us say, for some reason (which is uninteresting for the purposes of this discussion), we need two different implementations of a particular function which takes an int and a double as input. This is easy; we can give each function a different name:
However, there are certain operations for which we can't have two different names; for instance overloaded operators and constructors. If we want to write a class which has two different constructors, both of which logically needs an int and a double as input, the foo/foo_special_case technique won't work; so we 'colour' the constructor with an extra parameter which is not named and is not used:
1 2 3 4 5 6 7
struct A
{
A( int count, double ratio ) ;
struct for_special_occasions {} ;
A( int count, double ratio, for_special_occasions /* not used */ ) ;
};
Tag dispathing uses function colouring to determine which template function is to be instantiated.
template <typename T>
struct Some_Struct
{
typedef T Type; //some typedef
};
template<typename T>
void functionX ( typename Some_Struct<T>::Type param ) //See below
{
//do stuff
}
int main()
{
//The following cannot be instantiated because parameters
//of of the form typename Some_Struct<T>::inner_Type do
//not take part in template parameter deduction -so we will
//need another parameter that can be deduced
functionX( int() ); //Template parameter deduction failuire
}
//------------------------------------------------------------
//--------------------------------------------------------------
//A way to resolve the above issue
template <typename T>
struct Helper
{
};
template <typename T>
struct Some_Struct
{
typedef T Type; //some typedef
};
//We add a simple parameter to the function
//it won't be used - but it is in a form
//where the template parameter can be deduced
template<typename T>
void functionX ( typename Some_Struct<T>::Type param , Helper<T> )
{
//do stuff
}
int main()
{
functionX( int(), Helper<int>() );
}