c++ - 如果函数模板已经推断出返回类型,有没有办法在不实例化定义的情况下调用它?

标签 c++ templates language-lawyer

考虑一些函数模板,例如:

template <class T>
const auto& foo() { static T t; return t; }
如果 T 则定义无效应该是 void .尽管如此,我们可以单独实例化声明而不触发错误:
extern template const auto& foo<void>();  // explicit instantiation declaration
现在让我们考虑 foo 的情况。被调用,而不是被显式实例化。显然,如果 foo曾经在评估的上下文中调用,特化的定义将被实例化。在未经评估的情况下呢?我们知道,如果在未计算的上下文中调用具有非推导返回类型的函数模板,则不会实例化特化的定义。最明显的例子是 std::declval<T> .尚不清楚对于具有推导返回类型的函数是否可以这样做。
例如,我考虑过这个:
static_assert(sizeof( (void)foo<void>(), char{} ) == 1);
然而,即使在这种情况下,编译器肯定有足够的信息来评估 sizeof在不知道返回类型的情况下,仍然会出现编译错误(godbolt link)。
  • 标准的哪些规定需要实例化 foo<void> 的定义在这个情况下?
  • 有没有办法foo<void>可以在不会实例化其定义的未评估表达式中调用吗?
  • 最佳答案

    What provision of the Standard requires the instantiation of the definition of foo<void> in this situation?


    [dcl.spec.auto]/11 中的注释尽管是非规范性的确实提到任何特殊化的使用(在其声明的返回类型中具有占位符的函数模板)将导致隐式实例化 [extract, 重点矿]:

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


    而且,[dcl.spec.auto]/14涵盖了允许显式实例化声明而不触发实例化的特殊情况,同时也暗示了为确定函数模板的返回类型而触发的实例化机制与“常规”实例化机制有些分离[]重点矿]:

    An explicit instantiation declaration does not cause the instantiation of an entity declared using a placeholder type, but it also does not prevent that entity from being instantiated as needed to determine its type. [ Example:

    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
    

     — end example ]


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

    Is there any way that foo<void> can be called inside an unevaluated expression that would not instantiate its definition?


    鉴于上述讨论,我会说:不。即使在未评估的表达式中调用也将属于(非规范)“任何使用”。

    关于c++ - 如果函数模板已经推断出返回类型,有没有办法在不实例化定义的情况下调用它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64915753/

    相关文章:

    当类模板 "*"包装在宏中时,C++ 的参数太少

    c++ - 为什么这个指针为空

    c - 当 NULL 不是全零位时,全零位指针值也是 'false' 吗?

    c++ - 本地结构通过使用通用模板函数影响不同的翻译单元

    c++ - 如何从 vector 初始化数组? (如何将指针转换为数组?)

    c++ - WAVE 文件的恐惧失败

    c++ - C++ 编译器必须选择两个转换运算符中的哪一个?

    传递字符串的 C++ 非 POD 警告?

    c++ - std::initializer_list 的类型推断

    python - 找不到 Djangos TEMPLATE_DIRS