类和函数之间模板缺乏正交性

时间:2010-09-30 10:40:01

标签: c++ templates

// InternalTemplate.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

template<class T>
struct LeftSide
{
 static void insert(T*& newLink, T*& parent)
 {
  parent->getLeft() = newLink;
  newLink->parent = newLink;
 }
};

template<class T>
struct Link
{
 T* parent_;
 T* left_;
 T* right_;
 T*& getParent()const
 {
  return parent_;
 }
 template<class Side>
 void plugIn(Link<T>*& newLink);


};

template<class T>
template<class Side>
void Link<T>::plugIn(Link<T>*& newLink)//<<-----why can't I type  
//void Link<T>::plugIn<Side>(Link<T>*& newLink)<---<Side> next to plugIn


{
 Side::insert(newLink,this);
}

int _tmain(int argc, _TCHAR* argv[])
{
 return 0;
}

我觉得奇怪的是我必须为类指定参数但不能为函数指定参数。有什么理由吗?

3 个答案:

答案 0 :(得分:2)

函数模板和类模板是互补的(我称之为正交,但你可以自由地不同意),并且在模板元编程中它们实际上用于正交目的。

类模板允许您在模板参数上进行模式匹配,即。他们提供部分专业化

相反,函数模板不允许部分特化,但它们允许模板参数推导,这意味着您不必显式写入模板参数(除了额外的参数,如你的例子)。

我认为,这解释了语法上的差异,因为它们可以实现的不同。而且,函数模板可以有重载,类模板不能。

结合这两个概念的方法是

1)如果你想要对函数模板进行部分特化,那么使用带有静态非模板函数的辅助类模板:

template <typename T>
struct doSomethingWithPointersHelper
{
    static void act(T x) { ... }
};

template <typename T>
struct doSomethingWithPointersHelper<T*>
{
    static void act(T* x) { ... }
};

// This acts as if we had a partial specialization
// for pointer types
template <typename T>
doSomethingWithPointers(T x)
{ return doSomethingWithPointersHelper<T>::act(x); }

在特定情况下还有其他方法可以实现这一点,但这种方法始终有效。

2)如果你想在构造复杂类时使用参数推导,那么要有辅助模板函数:

template <typename T, typename U>
struct MyComplexClass
{ ... };

template <typename T, typename U>
MyComplexClass<T, U> makeComplex(T t, U u)
{ return MyComplexClass<T, U>(t, u); }

在标准库中,您会找到使用此技术的make_pairbind1stmem_fun

答案 1 :(得分:1)

$14/2 -

  

模板声明只能作为命名空间范围或类范围声明出现。 在函数模板声明中,declarator-id的最后一个组件应该是template-name或operator-functionid(即,不是template-id)。 [注意:在类模板声明中,如果类名是simple-template-id,则声明声明一个类模板部分特化(14.5.5)。 - 后注]“

标准明确禁止这种语法。有关template id / template name

的更多信息,请参阅此处

答案 2 :(得分:0)

您需要专注于Link结构,以便定义它的模板成员函数。

template<>
template<class Side>
void Link<int>::plugIn(Link<int>*& newLink)
{
 Side::insert(newLink,this);
}

说实话,这让我的大脑爆炸了一点。