Function signature-like expressions as C++ template arguments
- by Jeff Lee
I was looking at Don Clugston's FastDelegate mini-library and noticed a weird syntactical trick with the following structure:
TemplateClass< void( int, int ) > Object;
It almost appears as if a function signature is being used as an argument to a template instance declaration.
This technique (whose presence in FastDelegate is apparently due to one Jody Hagins) was used to simplify the declaration of template instances with a semi-arbitrary number of template parameters.
To wit, it allowed this something like the following:
// A template with one parameter
template<typename _T1>
struct Object1
{
_T1 m_member1;
};
// A template with two parameters
template<typename _T1, typename _T2>
struct Object2
{
_T1 m_member1;
_T2 m_member2;
};
// A forward declaration
template<typename _Signature>
struct Object;
// Some derived types using "function signature"-style template parameters
template<typename _Dummy, typename _T1>
struct Object<_Dummy(_T1)> : public Object1<_T1> {};
template<typename _Dummy, typename _T1, typename _T2>
struct Object<_Dummy(_T1, _T2)> : public Object2<_T1, _T2> {};
// A. "Vanilla" object declarations
Object1<int> IntObjectA;
Object2<int, char> IntCharObjectA;
// B. Nifty, but equivalent, object declarations
typedef void UnusedType;
Object< UnusedType(int) > IntObjectB;
Object< UnusedType(int, char) > IntCharObjectB;
// C. Even niftier, and still equivalent, object declarations
#define DeclareObject( ... ) Object< UnusedType( __VA_ARGS__ ) >
DeclareObject( int ) IntObjectC;
DeclareObject( int, char ) IntCharObjectC;
Despite the real whiff of hackiness, I find this kind of spoofy emulation of variadic template arguments to be pretty mind-blowing.
The real meat of this trick seems to be the fact that I can pass textual constructs like "Type1(Type2, Type3)" as arguments to templates. So here are my questions: How exactly does the compiler interpret this construct? Is it a function signature? Or, is it just a text pattern with parentheses in it? If the former, then does this imply that any arbitrary function signature is a valid type as far as the template processor is concerned?
A follow-up question would be that since the above code sample is valid code, why doesn't the C++ standard just allow you to do something like the following, which is does not compile?
template<typename _T1>
struct Object
{
_T1 m_member1;
};
// Note the class identifier is also "Object"
template<typename _T1, typename _T2>
struct Object
{
_T1 m_member1;
_T2 m_member2;
};
Object<int> IntObject;
Object<int, char> IntCharObject;