// 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;
}
我觉得奇怪的是我必须为类指定参数但不能为函数指定参数。有什么理由吗?
答案 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_pair
,bind1st
或mem_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);
}
说实话,这让我的大脑爆炸了一点。