模板化成员函数的语法(Syntax for Templated Member Functions)

请考虑以下代码:

template <typename Datatype> class MyClass { void doStuff(); template <typename AnotherDatatype> void doTemplateStuff(AnotherDatatype Argument); }; template <typename Datatype> void MyClass<Datatype>::doStuff() { // ... } template <typename Datatype> template <typename AnotherDatatype> void MyClass<Datatype>::doTemplateStuff(AnotherDatatype Argument) { // ... }

如果我像这样压缩它,第二个成员函数doTemplateStuff的实现将无法编译:

template <typename Datatype, typename AnotherDatatype> void MyClass<Datatype>::doTemplateStuff(AnotherDatatype Argument) { // ... }

为什么是这样? 不能用逗号分隔模板信息与将每个typename放在自己的行上具有相同的效果吗? 或者是否有一些我不知道的微妙差异......?

(另外,如果有人能想到更好的标题,请告诉我。)

Consider the following code:

template <typename Datatype> class MyClass { void doStuff(); template <typename AnotherDatatype> void doTemplateStuff(AnotherDatatype Argument); }; template <typename Datatype> void MyClass<Datatype>::doStuff() { // ... } template <typename Datatype> template <typename AnotherDatatype> void MyClass<Datatype>::doTemplateStuff(AnotherDatatype Argument) { // ... }

The implementation for the second member function, doTemplateStuff, will not compile if I condense it like this:

template <typename Datatype, typename AnotherDatatype> void MyClass<Datatype>::doTemplateStuff(AnotherDatatype Argument) { // ... }

Why is this? Shouldn't separating template information by commas have the same effect as putting each typename on its own line? Or is there some subtle difference I'm not aware of...?

(Also, if someone can think of a better title please let me know.)

最满意答案

这是一个很好的问题。 我不知道标准委员会决定以这种方式设计模板的具体原因,但我认为这是对lambda演算和类型理论的回调。 从数学上讲,任何带有两个参数并返回一个值的函数和一个接受单个参数的函数之间都存在同构,然后返回一个接受另一个参数然后返回一个值的函数。 例如:

λx。 λy。 x + y

是同形的(但不完全相同)

λ(x,y)。 x + y

其中(x,y)是表示x和y对的单个对象。

使用C ++成员函数模板,C ++选择使用这些系统中的第一个。 您必须为最外层函数指定所有参数,然后单独指定最内层函数的所有参数。 在数学上,这相当于在一个参数列表中同时指定所有参数,但C ++没有选择这样做。

现在,一个非常好的问题是他们为什么不这样做。 我不完全确定基本原理,但如果我不得不猜测它是因为与模板专业化的奇怪交互。 如果我能想到具体的东西,我会更新这篇文章。

This is an excellent question. I don't know the specific reason that the standards committee decided to design templates this way, but I think it's a callback to lambda calculus and type theory. Mathematically speaking, there is an isomorphism between any function that takes two arguments and returns a value and a function that takes in a single argument, then returns a function that takes in yet another argument and then returns a value. For example:

λx. λy. x + y

is isomorphic with (but not identical to)

λ(x, y). x + y

where (x, y) is a single object representing the pair of x and y.

With C++ member function templates, C++ chose to use the first of these systems. You have to specify all the arguments for the outermost function, then, separately, all of the arguments for the innermost function. Mathematically this is equivalent to specifying all of the arguments at the same time in one argument list, but C++ didn't choose to do this.

Now, a really good question is why they didn't do this. I'm not fully sure of the rationale, but if I had to guess it's because of weird interactions with template specialization. If I can think of something specific I'll update this post.

模板化成员函数的语法(Syntax for Templated Member Functions)

请考虑以下代码:

template <typename Datatype> class MyClass { void doStuff(); template <typename AnotherDatatype> void doTemplateStuff(AnotherDatatype Argument); }; template <typename Datatype> void MyClass<Datatype>::doStuff() { // ... } template <typename Datatype> template <typename AnotherDatatype> void MyClass<Datatype>::doTemplateStuff(AnotherDatatype Argument) { // ... }

如果我像这样压缩它,第二个成员函数doTemplateStuff的实现将无法编译:

template <typename Datatype, typename AnotherDatatype> void MyClass<Datatype>::doTemplateStuff(AnotherDatatype Argument) { // ... }

为什么是这样? 不能用逗号分隔模板信息与将每个typename放在自己的行上具有相同的效果吗? 或者是否有一些我不知道的微妙差异......?

(另外,如果有人能想到更好的标题,请告诉我。)

Consider the following code:

template <typename Datatype> class MyClass { void doStuff(); template <typename AnotherDatatype> void doTemplateStuff(AnotherDatatype Argument); }; template <typename Datatype> void MyClass<Datatype>::doStuff() { // ... } template <typename Datatype> template <typename AnotherDatatype> void MyClass<Datatype>::doTemplateStuff(AnotherDatatype Argument) { // ... }

The implementation for the second member function, doTemplateStuff, will not compile if I condense it like this:

template <typename Datatype, typename AnotherDatatype> void MyClass<Datatype>::doTemplateStuff(AnotherDatatype Argument) { // ... }

Why is this? Shouldn't separating template information by commas have the same effect as putting each typename on its own line? Or is there some subtle difference I'm not aware of...?

(Also, if someone can think of a better title please let me know.)

最满意答案

这是一个很好的问题。 我不知道标准委员会决定以这种方式设计模板的具体原因,但我认为这是对lambda演算和类型理论的回调。 从数学上讲,任何带有两个参数并返回一个值的函数和一个接受单个参数的函数之间都存在同构,然后返回一个接受另一个参数然后返回一个值的函数。 例如:

λx。 λy。 x + y

是同形的(但不完全相同)

λ(x,y)。 x + y

其中(x,y)是表示x和y对的单个对象。

使用C ++成员函数模板,C ++选择使用这些系统中的第一个。 您必须为最外层函数指定所有参数,然后单独指定最内层函数的所有参数。 在数学上,这相当于在一个参数列表中同时指定所有参数,但C ++没有选择这样做。

现在,一个非常好的问题是他们为什么不这样做。 我不完全确定基本原理,但如果我不得不猜测它是因为与模板专业化的奇怪交互。 如果我能想到具体的东西,我会更新这篇文章。

This is an excellent question. I don't know the specific reason that the standards committee decided to design templates this way, but I think it's a callback to lambda calculus and type theory. Mathematically speaking, there is an isomorphism between any function that takes two arguments and returns a value and a function that takes in a single argument, then returns a function that takes in yet another argument and then returns a value. For example:

λx. λy. x + y

is isomorphic with (but not identical to)

λ(x, y). x + y

where (x, y) is a single object representing the pair of x and y.

With C++ member function templates, C++ chose to use the first of these systems. You have to specify all the arguments for the outermost function, then, separately, all of the arguments for the innermost function. Mathematically this is equivalent to specifying all of the arguments at the same time in one argument list, but C++ didn't choose to do this.

Now, a really good question is why they didn't do this. I'm not fully sure of the rationale, but if I had to guess it's because of weird interactions with template specialization. If I can think of something specific I'll update this post.