如果函数模板具有推导的返回类型,是否可以在不实例化定义的情况下调用它? [英] If a function template has deduced return type, is there a way to call it without instantiating the definition?

查看:42
本文介绍了如果函数模板具有推导的返回类型,是否可以在不实例化定义的情况下调用它?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑一些功能模板,例如:

Consider some function template such as:

template <class T>
const auto& foo() { static T t; return t; }

如果 T void ,则该定义无效.但是,我们可以单独实例化声明而不触发错误:

The definition would not be valid if T were to be void. Nonetheless, we are allowed to instantiate the declaration alone without triggering an error:

extern template const auto& foo<void>();  // explicit instantiation declaration

现在让我们考虑调用 foo 而不是显式实例化的情况.显然,如果曾经在受评估的上下文中调用 foo ,则将实例化专门化的定义.在未经评估的情况下呢?我们知道,如果在未求值的上下文中调用具有非推断返回类型的函数模板,则不会实例化专门化的定义.显而易见的例子是 std :: declval< T> .尚不清楚对于推导的返回类型的函数是否可以实现相同的目的.

Now let's consider situations where foo is called, rather than being explicitly instantiated. Obviously, if foo is ever called in an evaluated context, the definition of the specialization will be instantiated. What about in an unevaluated context? We know that if a function template with a non-deduced return type is called in an unevaluated context, the definition of the specialization is not instantiated. The obvious example of this is std::declval<T>. It's not clear whether the same is possible for a function that has a deduced return type.

例如,我考虑过:

static_assert(sizeof( (void)foo<void>(), char{} ) == 1);

但是,即使在这种情况下,即使编译器确实具有足够的信息来评估 sizeof 表达式而又不知道返回类型,仍会发生编译错误(

However, even in this situation, where the compiler definitely has enough information to evaluate the sizeof expression without knowing the return type, a compilation error still occurs (godbolt link).

  • 在这种情况下,该标准的哪些规定要求实例化 foo< void> 的定义?
  • 是否可以在未实例化其表达式的未求值表达式中调用 foo< void> ?

推荐答案

在这种情况下,该标准的哪些规定要求实例化 foo< void> 的定义?

尽管不是规范性的,但 [dcl.spec.auto]/11 确实提到任何专门化(函数模板在声明的返回类型中带有占位符的函数模板)的使用会导致隐式实例化[extract,强调我的]:

Albeit non-normative, the note in [dcl.spec.auto]/11 does mention that any use of a specialization (of a function template with a placeholder in its declared return type) will cause an implicit instantiation [extract, emphasis mine]:

[...] [注意:"因此,对功能模板的任何特殊化使用都会导致隐式实例化.

[...] [ Note: Therefore, any use of a specialization of the function template will cause an implicit instantiation.

,此外, [dcl.spec.auto]/14 涵盖了在不触发实例化的情况下允许显式实例化声明的特定情况,同时可以说还暗示了为确定功能模板的返回类型而触发的实例化机制与常规"机制有所不同.实例化机制[强调我的]:

and, moreover, [dcl.spec.auto]/14 covers the particular case of allowing an explicit instantiation declaration without triggering an instantiation, whilst arguably also hinting that the instantiation mechanisms triggered for determining the return type for a function template are somewhat separated from the "regular" instantiation mechanisms [emphasis mine]:

显式实例化声明不会导致使用占位符类型声明的实体的实例化,,但是也不会阻止该实体根据需要实例化以确定其类型.[示例:

template <typename T> auto f(T t) { return t; }
extern template auto f(int);    // does not instantiate f<int>
int (*p)(int) = f;              // instantiates f<int> to determine its return type, but an explicit
                                // instantiation definition is still required somewhere in the program

最终示例]

该示例的注释(非规范性)指出,这种特殊情况触发的隐式实例化仅用于返回类型推导,而无需放弃其他地方的显式实例化定义.

where the comment (non-normative) to the example points out that such a special-case triggered implicit instantiation is only used for return type deduction, and does not waive the need for an explicit instantiation definition elsewhere.

在没有实例化其定义的未求值表达式中,是否可以以任何方式调用 foo< void> ?

鉴于上面的讨论,我会说:不.即使在未经评估的表达式内进行调用也将属于(非规范性)对...的任何使用".

Given the discussion above, I would say: no. Calling even within an unevaluated expression would fall under the (non-normative) "any use of".

这篇关于如果函数模板具有推导的返回类型,是否可以在不实例化定义的情况下调用它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆