显式实例化

发布于 2024-09-19 08:07:06 字数 673 浏览 1 评论 0原文

这是由这篇文章(第5页)激发

template<class T> 
T const &f(T const &a, T const &b){
    return (a > b ? a : b);
}

template int const &f<int>(int const &, int const &);

int main(){
    int x = 0, y = 0;
    short s = 0;
    f(x, y);     // OK
    f(x, s);     // Is this call well-formed?
}

'f(x, s)' 格式良好?我假设由于函数模板 'f' 已显式实例化,因此将应用标准转换,因此 'short s' 将转换为 'int'< /code> 匹配对显式特化 'f' 的调用。但这似乎格式不正确?

标准的哪一部分讨论了这种情况下的适用规则?

This was motivated by this article (page 5)

template<class T> 
T const &f(T const &a, T const &b){
    return (a > b ? a : b);
}

template int const &f<int>(int const &, int const &);

int main(){
    int x = 0, y = 0;
    short s = 0;
    f(x, y);     // OK
    f(x, s);     // Is this call well-formed?
}

Is the call 'f(x, s)' well-formed? I assumed that since the function template 'f' is explicitly instantiated, standard conversions would be applied and hence 'short s' would be converted to 'int' to match the call to the explicit specialization 'f<int>'. But it appears that this is ill-formed?

Which part of the Standard talks about the applicable rules in this context?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

∞觅青森が 2024-09-26 08:07:07

不,调用 f(x, s) 的格式不正确。由于您没有明确声明要使用的专业化,编译器会使用参数推导来尝试实例化函数模板;这会失败,因为 xs 具有不同的类型,因此 T 不明确。

适用的规则在 13.3.1 中的重载解析过程规范中:

在候选函数模板的每种情况下,候选函数模板特化都是使用模板参数推导生成的(14.8.3、14.8.2)。然后,这些候选函数将按照通常的方式作为候选函数进行处理。

14.8.3/1 也相关:

对于每个函数模板,如果参数推导和检查成功,则使用模板参数(推导的和/或显式的)来实例化单个函数模板专业化,该函数模板专业化将添加到要在重载决策中使用的候选函数集。如果对于给定的函数模板,参数推导失败,则不会将此类函数添加到该模板的候选函数集中。

函数模板已为 T = int 显式实例化,但编译器不知道应该使用此实例化,直到执行模板参数推导以确定 T 应该做什么是。

No, the call f(x, s) is not well-formed. Since you do not explicitly state the specialization to be used, the compiler uses argument deduction to attempt to instantiate the function template; this fails because x and s have different types so T is ambiguous.

The applicable rule is in the specification of the overload resolution process in 13.3.1:

In each case where a candidate is a function template, candidate function template specializations are generated using template argument deduction (14.8.3, 14.8.2). Those candidates are then handled as candidate functions in the usual way.

14.8.3/1 is also relevant:

For each function template, if the argument deduction and checking succeeds, the template arguments (deduced and/or explicit) are used to instantiate a single function template specialization which is added to the candidate functions set to be used in overload resolution. If, for a given function template, argument deduction fails, no such function is added to the set of candidate functions for that template.

The function template is explicitly instantiated for T = int, but the compiler doesn't know that it should use this instantiation until after it performs template argument deduction to determine what T should be.

剩余の解释 2024-09-26 08:07:07

调用 f(x, s) 在语法上是正确的,但编译器将无法从中推导出模板参数 T,因为它可能是一个 intshort (因为第一个和第二个参数)。实例化模板没有帮助,它仅指示编译器编译该专业化并将其添加到生成的目标文件中。

如果您希望调用自动将 s 转换为 int,请使用 f(x, s)

The call f(x, s) is syntactically well-formed, but the compiler will not be able to deduce the template parameter T from it because is could a int or a short (because of the first and second arguments). Instantiating the template does not help, that only indicates the compiler to compile that specialization and add it to the generated object file.

If you want the call to cast s to a int automatically, use f<int>(x, s).

記柔刀 2024-09-26 08:07:07

显式实例化的专业化没有任何更高的优先级或优惠待遇。从实例化的角度来看,它只是完整地存在。对图书馆有用。

编译器根本无法确定要转换哪个参数,并且会像没有额外声明一样陷入困境。

顺便说一句,如果您返回对已转换参数的引用,则一旦临时过期,它将悬空。如果参数是对不同类型的引用,则无法正确形成返回值。

这是我更新的 min

#include <type_traits>

template< typename A, typename B >
typename std::common_type< A, B >::type // cannot return ref
my_min( A const &a, B const &b ) {
    return a < b? a : b;
}

 // enable_if< is_same< A, B > > the old, return-by-reference impl

int main() {
    int q = my_min( short(5), long(3) );
}

An explicitly instantiated specialization doesn't have any higher priority or preferential treatment. It simply exists in its entirety from the point of instantiation. Useful for libraries.

The compiler simply can't figure out which argument to convert, and gets stuck just as it would without the extra declaration.

By the way, if you return it a reference to an argument which was converted, it will be dangling once the temporary expires. If the arguments are references to different types, there is no way to properly form the return value.

Here is my updated min:

#include <type_traits>

template< typename A, typename B >
typename std::common_type< A, B >::type // cannot return ref
my_min( A const &a, B const &b ) {
    return a < b? a : b;
}

 // enable_if< is_same< A, B > > the old, return-by-reference impl

int main() {
    int q = my_min( short(5), long(3) );
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文