类似于C ++模板参数的函数签名式expression式

我在看Don Clugston的FastDelegate迷你库,注意到一个奇怪的语法窍门,结构如下:

TemplateClass< void( int, int ) > Object; 

它几乎看起来好像一个函数签名被用作模板实例声明的参数。

这种技术(其在FastDelegate中的存在显然是由于一个Jody Hagins)被用来简化具有半任意数量的模板参数的模板实例的声明。

就机智而言,它允许这样的事情如下所示:

 // 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; 

尽pipe真的有点ha,,但我觉得这种可变的模板参数的欺骗性仿真很令人兴奋。

这个技巧的真正好处在于,我可以将“Type1(Type2,Type3)”这样的文本结构作为parameter passing给模板。 所以这里是我的问题:编译器如何解释这个结构? 这是一个函数签名? 或者,它只是一个带括号的文本模式吗? 如果前者,那么这是否意味着就模板处理器而言,任意函数签名都是有效的types?

后续的问题是,因为上面的代码示例是有效的代码,为什么C ++标准不允许你做下面的事情,而不是编译?

 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; 

关于你的第一个问题 – 有关int(char, float)的types – 这是一个有效的C ++types,是一个函数的types,它接受一个char和一个float并返回一个int 。 请注意,这是实际函数的types,而不是函数指针,它将是一个int (*) (char, float) 。 任何函数的实际types都是这种不寻常的types。 例如,types

 void DoSomething() { /* ... */ } 

void ()

这在常规编程中不会出现的原因是,在大多数情况下,您不能声明这种types的variables。 例如,这个代码是非法的:

 void MyFunction() { void function() = DoSomething; // Error! } 

但是,您真正看到使用函数types的一种情况是用于传递函数指针:

 void MyFunction(void FunctionArgument()) { /* ... */ } 

看到这种types的函数写入函数指针是比较常见的,但是接受函数本身是完全正确的。 它在幕后被铸造。

至于你的第二个问题,为什么用不同的参数编写相同的模板是不合法的,我不知道规范中完全禁止它的措辞,但是这与事实有关,声明一个类模板,你不能改变参数的数量。 然而,你可以提供一个局部特殊化的模板,它具有不同数量的参数,当然,部分特化只针对原始数量的参数。 例如:

 template <typename T> class Function; template <typename Arg, typename Ret> class Function<Ret (Arg)> { /* ... */ }; 

这里, Function总是需要一个参数。 模板专门化有两个参数,但专业化仍然只有一个types(具体来说, Ret (Arg) )。

 int* int_pointer; // int_pointer has type "int*" int& int_reference; // int_reference has type "int&" int int_value; // int_value has type "int" void (*function_pointer)(int, int); // function_pointer has type // "void (*)(int, int)" void (&function_reference)(int, int); // function_reference has type // "void (&)(int ,int)" void function(int, int); // function has type // "void(int, int)" template<> struct Object1<void(int, int)> { void m_member1(int, int); // wait, what?? not a value you can initialize. };