gpt4 book ai didi

c++ - 模板函数中默认参数的实例化点

转载 作者:行者123 更新时间:2023-12-01 13:42:35 26 4
gpt4 key购买 nike

当从非模板上下文引用函数模板时,该标准允许在封闭的命名空间范围声明之后或在转换单元的末尾实例化函数模板:[temp.point]/1

For a function template specialization, a member function template specialization, or a specialization for a member function or static data member of a class template, if the specialization is implicitly instantiated because it is referenced from within another template specialization and the context from which it is referenced depends on a template parameter, the point of instantiation of the specialization is the point of instantiation of the enclosing specialization. Otherwise, the point of instantiation for such a specialization immediately follows the namespace scope declaration or definition that refers to the specialization.



[temp.point]/8

A specialization for a function template, a member function template, or of a member function or static data member of a class template may have multiple points of instantiations within a translation unit, and in addition to the points of instantiation described above, for any such specialization that has a point of instantiation within the translation unit, the end of the translation unit is also considered a point of instantiation. A specialization for a class template has at most one point of instantiation within a translation unit. A specialization for any template may have points of instantiation in multiple translation units. If two different points of instantiation give a template specialization different meanings according to the one-definition rule, the program is ill-formed, no diagnostic required.



现在考虑这个最小的可重现示例:
#include <iostream>
#include <array>
struct A {};
std::array<char, 2> show(float, A)
{
std::cout << "2\n";
return {};
}
template<typename T>
struct Fun {
decltype(show(0, T{})) b;
};
template <typename T>
void func(T, int c = sizeof(Fun<T>{}.b))
{
show(0, T{});
std::cout << c << '\n';
}
int main()
{
func(A{});
}
char show(int, A)
{
std::cout << "1\n";
return {};
}

GCC 和 Clang 输出 1 2 ( godbolt )。

这里是 func<A>的实例化(在 main 中触发)有两个实例化点:一个紧跟在 main 之后(因此在第二个 show 之前)和另一个在翻译单元的末尾。第一 1表示编译器要实例化 func<A>在翻译单元的末尾。但是,默认参数 sizeof(Fun<T>{}.b)原因 Fun<A>被实例化,第二个 2建议 Fun<A>在第二个 show 之前实例化.

现在,默认参数的实例化点被指定为 func<A> : [temp.point]/2

If a function template or member function of a class template is called in a way which uses the definition of a default argument of that function template or member function, the point of instantiation of the default argument is the point of instantiation of the function template or member function specialization.



嗯……这好像暗示这两个数字应该是一样的。

我觉得我在这里错过了一些东西。有没有什么细节我碰巧忽略了?还是我犯了错误?

最佳答案

正如问题 [temp.point]/8 中引用的那样说:

If two different points of instantiation give a template specialization different meanings according to the one-definition rule, the program is ill-formed, no diagnostic required.



根据单一定义规则,如果定义中使用的名称的函数调用重载解析将产生定义外定义的不同实体,则两个定义是不同的。 ( [basic.def.odr]/6.2 )

show 的两次调用的重载解析在 func<A>并在 Fun<A>会根据 func<A> 是否选择不同的函数重载的实例化点紧跟在 main 之后或在翻译单元的末尾,两者都是允许的实例化点。

因此程序格式错误,不需要诊断。

关于c++ - 模板函数中默认参数的实例化点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60931139/

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