与用于 C++ 的 ISO 标准保持一致

Kate Gregory

Gregory Consulting

适用于:

Microsoft Visual C++_ .NET 2003

Microsoft Visual C++_ Toolkit 2003

Microsoft Visual Studio .NET

摘要:演示 Visual C++ 如何用于将 .NET 框架合并到 C++ 应用程序中。

本文是 Visual C++ 工具包 2003 随附的代码示例的一部分,可以从 https://msdn.microsoft.com/visualc/vctoolkit2003 下载。

本页内容

模板专用化 模板专用化
示例 示例
编译与运行 编译与运行
小结 小结
相关书籍 相关书籍

Microsoft Visual C++_ .NET 2003 遵循任何 Visual C++ 版本最高级别的标准。Visual C++ 于 1993 年首次发布,而 ISO C++ 标准则诞生于 1997 年。自标准发布以来,Visual C++ 的每个版本都变得更加一致,并且该版本获得了大约 98% 的一致性。(接受了标准化测试套件的行业都没有比较或度量过 C++ 编译器实施。三个常用的套件是 Dinkumware、Perennial 和 Plum Hall。Visual C++ .NET 2003 对三个套件都进行了测试)。

这种高级别的一致性使 Visual C++ .NET 2003 能够编译常用的现代 C++ 库(包括 LOKI、BOOST 和 BLITZ),这是一种由少数(如果有)其他编译器获得的特性。

编译该库的一个重要的标准语言功能是局部模板专用化,该示例演示了这种功能。尝试用其他编译器进行编译;例如,Visual C++ 2002 产生错误消息并且不能进行编译。

模板专用化

模板通常使用一个或多个占位符(表示类或类型)定义类或函数。在编译时,生成模板的实例以匹配代码中模板的使用。例如,该模板函数可用来比较整数、浮点数,或定义 > 运算符的任何类的实例:

template 
T biggest(T a, T b)
{
   if (a > b)  return a;
   return b;
}

您可以使用该模板,如下所示:

int x = biggest(3,4);
double d = biggest(4.1, -2.3);

// SalesRep instances created elsewhere, 
// operator> defined for SalesRep class
SalesRep bestseller = biggest(John, Jane); 

编译器将产生 biggest(int,int)biggest(double, double)biggest(SalesRep, SalesRep) 的代码,该代码将连接到可执行文件。

C++ 程序员通常在遇到需要处理字符串的模板时会面临麻烦。传统的 char* 字符串不能用 > 和 < (这些运算符只能比较指针值,而不能比较他们所指向的字符串)进行比较,或者像数值或对象那样用 = 进行复制。一种解决办法是编写专用化 —特定类型的一个实例,编译器将使用该实例而不是更通用的模板。以下是 biggest()char* 类型的专用化:

template<> 
const char* biggest(const char* a, const char* b)
{
   if (strcmp(a,b) > 0)  return a;
   return b;
}

Visual C++ 一直以来都能够处理模板专用化。2003 版中新增的功能是处理局部 模板专用化。这适用于采用两个占位符类型的模板,而不适用于只采用一个占位符类型的模板,如 biggest()

示例

集合类尤其经常使用多个占位符。查找表所包含的值(数值、Employee 实例或日期、char* 字符串)由类型为整数、char* 字符串或日期的键索引。Pair 模板是使用两个占位符的简单类:

template <class A, class B>
class Pair
{
private:
    A index;
    B value;
public:
    Pair(A aa, B bb):index(aa),value(bb) {}
    void display(){cout << index << ' ' << value << endl;}
    bool operator>(const Pair<A,B>& p) { return index>p.index;}
};

Pair 并未作许多工作,但您可以想象相似的代码在灵活的集合解决方案的核心出现。它拥有索引和值的附件,显示它们,并且可以通过仅比较它们的值来比较两个 Pair 实例。当索引类型 A 是整数或其他数值类型,或者是已经执行了运算符的类时,它可以完全正确的运行。>.当索引类型是 char* 时,比较就没有意义了,因为 > 比较字符指针的数值地址,而不是它指向的字符。另外,索引的初始化不会产生字符的副本,只会产生指针的副本。

局部模板专用化是这样一种专用化:用特定类型代替一个占位符(本例中为 char*),而另一个则不需要。对于 Pairchar* 索引值的局部专用化如下所示:

template <class B>
class Pair<char*, B>
{
private:
    char* index;
    B value;
public:
    Pair(char* aa, B bb):value(bb) {index = new char[strlen(aa)];
 strcpy(index,aa);}
    void display() {cout << index << ' ' << value << endl;}
    bool operator>(const Pair<char*, B>& p)
     { return ( strcmp(index,p.index) > 0);}
};

上述代码在以前的 Visual C++ 版本下不能编译。然而,从 Visual C++ .NET 2003 版本以后,它就可以编译了。

编译与运行

本示例中的 main() 创建不同的 Pair 并将它们进行比较:

int main(int argc, char* argv[])
{
    Pair<double,int> first(2.2,3);
    first.display();
    Pair<double,int> second(2.1,4);
    second.display();
    if (first > second)
        cout << "first is greater" << endl;
    else
        cout << "first is not greater" << endl;
    Pair<char*,int> third("Hello",4);
    third.display();
    Pair<char*,int> fourth("World",5);
    fourth.display();
    if (third > fourth)
        cout << "third is greater" << endl;
    else
        cout << "third is not greater" << endl;

    return 0;
}

要编译该示例,请使用以下命令行:

cl /EHsc conformance.cpp

要运行:

conformance

您可以看到以下输出:

2.2 3
2.1 4
first is greater
Hello 4
World 5
third is not greater

Pair 显示第一个更大,因为 2.2 大于 3。Pair 显示小于等于,因为“Hello”不大于“World”。

小结

局部模板专用化是编写丰富而有用的集合的重要技术。在许多 C++ 程序中,它有许多用途,并且是 Visual C++ .NET 2003 中遵循标准的许多新领域之一.

有关 Visual C++ ISO C++ 与标准保持一致的详细信息,请参见 Visual C++ .NET 2003 Enhanced Compiler Conformance

相关书籍

Microsoft Visual C++ .Net 2003 Kick Start Kate Gregory

关于作者

Kate Gregory 是 Microsoft 的区域主管,C++ 的最有价值专家,并且是 Microsoft Visual C++ .NET 2003 Kick Start 一书的作者。她是Gregory Consulting 的创立合伙人,在北美提供咨询和开发服务,专注于用最前沿的技术软件开发、集成项目、技术编写、顾问和培训。

转到原英文页面