gpt4 book ai didi

c++ - c++模板规范和重载的解析

转载 作者:可可西里 更新时间:2023-11-01 16:03:02 26 4
gpt4 key购买 nike

我读过 Why Not Specialize Function Templates经过一点实验,我发现了一个有趣的事情。这是 main.cxx:

// main.cxx
#include <iostream>

// Declarations
/*
template<class T>
void foo(T);

template<>
void foo(int*);

template<class T>
void foo(T*);
*/

// Definition and specification
template<class T>
void foo(T x)
{
std::cout << "T version." << std::endl;
}

template<>
void foo(int *i)
{
std::cout << "int* version." << std::endl;
}

template<class T>
void foo(T *x)
{
std::cout << "T* version" << std::endl;
}

int main(int argc, char** argv)
{
int *p;
foo(p);
}

有趣的是:如果我对声明部分进行注释,行为就像文章所说的那样,即如果 int* 版本的定义在其定义之前,则将使用 T* 版本,反之亦然。但是,如果取消注释声明 block ,则无论我在定义或声明中使用哪种顺序,都只会调用 int* 版本。我的问题是该声明如何影响决议?

有什么想法吗?我在 x86_64-redhat-linux 上使用 g++ 4.2.2

编辑:在看到 AProgrammer 的回答后简化这个问题

最佳答案

将源代码分发到三个文件中只是混淆了事情:预处理使一个编译单元和行为仅取决于 CU 的内容而不是分发了多少文件。

我认为你对这种情况感到惊讶

#include <iostream>

template<class T> void foo(T); // A
template<> void foo(int*); // 1
template<class T> void foo(T*); // B

template<class T> void foo(T x)
{ std::cout << "T version." << std::endl; }

template<> void foo(int *i) // 2
{ std::cout << "int* version." << std::endl; }

template<class T> void foo(T *x)
{ std::cout << "T* version" << std::endl; }

int main(int argc, char** argv) {
int *p;
foo(p);
}

你得到 int* version .这是预期的行为。虽然 (1) 确实声明了 template <typename T> void foo(T) 的特化, (2) 不是该特化的定义。 (2) 定义并声明 template<class T> void foo(T*); 的特化然后在 main() 中调用.如果您在放置声明和定义的任何地方的三个定义之前给出三个声明,就会发生这种情况。定义 (2) 将始终看到声明 template<class T> void foo(T*);并因此成为它的特化。

当一个函数模板的特化被声明或定义时,它可以是多个函数模板的特化(像这里的 (2) 可以是两个重载 A 和 B 的特化,它们只需要被声明),它是“更专业”的特化。您可以在标准部分 17.5.5.2 中看到“更特化”的精确定义,但很容易看出 B 比 (2) 的 A 更匹配,因此 (2) 是 (B) 的特化. (1) 声明 (A) 的特化,因为当 (1) 被声明时, (B) 还没有出现。如果你想在看到 (B) 之后给出 (1) 的定义,你必须写成

template <> void foo<int*>(int*) // definition for (1)
{ std::cout << "foo<int*>(int*)\n"; }

你也可以在定义 (2) 时明确:

template<> void foo<int>(int *i) // 2 alternate
{ std::cout << "int* version." << std::endl; }

(但显然在同一个 CU 中给出 (2) 和这个替代版本会给你一个错误)。

您也可以在调用函数时显式显示:

foo(p); // call (2)
foo<int>(p); // call (2)
foo<int*>(p); // call (1)

关于c++ - c++模板规范和重载的解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6295575/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com