简体   繁体   English

函数签名式表达式作为C ++模板参数

[英]Function signature-like expressions as C++ template arguments

I was looking at Don Clugston's FastDelegate mini-library and noticed a weird syntactical trick with the following structure: 我正在看Don Clugston的FastDelegate迷你库,并注意到一个奇怪的语法技巧,具有以下结构:

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. 这种技术(其在FastDelegate中的存在显然是由于一个Jody Hagins)被用于简化模板实例的声明,其具有半任意数量的模板参数。

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. 这个技巧的真正原因似乎是我可以将像“Type1(Type2,Type3)”这样的文本结构作为模板的参数传递。 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 does not compile? 一个后续问题是,由于上面的代码示例是有效的代码,为什么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;

With regards to your first question - about the type int(char, float) - this is a valid C++ type and is the type of a function that takes in a char and a float and returns an int . 关于你的第一个问题 - 关于类型int(char, float) - 这是一个有效的C ++类型,是一个接受charfloat并返回int的函数的类型。 Note that this is the type of the actual function, not a function pointer, which would be an int (*) (char, float) . 请注意,这是实际函数的类型,而不是函数指针,它将是int (*) (char, float) The actual type of any function is this unusual type. 任何函数的实际类型都是这种不寻常的类型。 For example, the type of 例如,类型

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

is void () . void ()

The reason that this doesn't come up much during routine programming is that in most circumstances you can't declare variables of this type. 在常规编程期间没有出现太多的原因是在大多数情况下你不能声明这种类型的变量。 For example, this code is illegal: 例如,此代码是非法的:

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

However, one case where you do actually see function types used is for passing function pointers around: 但是,实际上看到使用的函数类型的一种情况是传递函数指针:

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

It's more common to see this sort of function written to take in a function pointer, but it's perfectly fine to take in the function itself. 更常见的是看到这种函数被写入函数指针,但是接受函数本身是完全正常的。 It gets casted behind-the-scenes. 它在幕后得到了。

As for your second question, why it's illegal to have the same template written with different numbers of arguments, I don't know the exactly wording in the spec that prohibits it, but it has something to do with the fact that once you've declared a class template, you can't change the number of arguments to it. 至于你的第二个问题,为什么使用不同数量的参数编写相同的模板是非法的,我不知道禁止它的规范中的确切措辞,但它与你曾经的事实有关声明了一个类模板,你不能改变它的参数个数。 However, you can provide a partial specialization over that template that has a different number of arguments, provided of course that the partial specialization only specializes over the original number of arguments. 但是,您可以对具有不同数量的参数的模板提供部分特化,当然,前提是部分特化仅专用于原始参数数量。 For example: 例如:

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

Here, Function always takes one parameter. 这里, Function总是带一个参数。 The template specialization takes in two arguments, but the specialization is still only over one type (specifically, Ret (Arg) ). 模板特化带有两个参数,但专门化仍然只有一种类型(特别是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.
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM