【问题标题】:Function candidates and declaration order候选函数和声明顺序
【发布时间】:2021-09-19 03:59:07
【问题描述】:

考虑以下 sn-p:

template<typename T>
int foo(T) {
  return 1;
}

struct my_struct{};

template<typename T>
int do_foo(T t) {
  return 
      foo(my_struct{}) + // 1   
      foo(t);            // 2 (via ADL)
}

int foo(my_struct) {
  return 2;
}

int main () {
  return do_foo(my_struct{});
} 

乍一看,对foo 的“非依赖”调用将返回1,而“依赖”调用将返回2

然而,在标准中我们发现the following paragraph:

如果调用将 <...> 找到更好的匹配项,则在 关联的命名空间考虑了所有函数声明 在所有翻译中这些名称空间中引入的外部链接 单位,而不仅仅是考虑模板中的那些声明 定义和模板实例化上下文,那么程序有 未定义的行为

不清楚这一段是否只讨论依赖名称查找 - 所以我想知道它是否适用于上述代码,从而使其格式错误。

您能否构造一个例子来说明这一段的意思?

【问题讨论】:

    标签: c++ templates language-lawyer


    【解决方案1】:

    整个段落仅适用于使用 ADL 解析的函数:

    对于后缀表达式是从属名称的函数调用 [...]
    如果电话会 [...]

    (这里的“调用”指的是每个调用都有一个依赖名称,所以这不适用于foo(my_struct{}),它不依赖)

    第二种情况被one definition rule覆盖:

    如果每个定义出现在不同的翻译单元中,并且提供的定义满足以下要求,则程序中可以有多个定义 [...] 非静态函数模板 [...]。给定这样一个名为 D 的实体在多个翻译单元中定义,那么

    • [...]
    • 在 D 的每个定义中,对应的名称,根据 [basic.lookup] 查找,应指在 D 的定义中定义的实体,或应指同一实体,经过重载解析和部分匹配后模板特化([temp.over]),[...]

    只要在其他翻译单元中int foo(my_struct) 的定义不位于template&lt;typename T&gt; int do_foo(T t) 的定义之前,您的代码就应该定义良好。


    以 [temp.dep.candidate] 为例,以下两个翻译单元的行为未定义:

    template<typename T>
    int foo(T) {
      return 1;
    }
    
    struct my_struct {};
    
    template<typename T>
    int do_foo(T t) {
      return foo(t);
    }
    
    int main() {
      return do_foo(my_struct{});
    }
    
    struct my_struct {};
    
    int foo(my_struct) {
      return 2;
    }
    

    (因为int foo(my_struct) 会更好匹配但在模板实例化上下文中找不到)

    【讨论】:

    • 谢谢!至于示例,我正在尝试构建不涉及违反 ODR 的东西,但仅基于定义的顺序和实例化点的“二元性”(调用站点和翻译结束)单元)。我曾经遇到过这样一个例子,但不记得它是什么样子了:)。
    猜你喜欢
    • 1970-01-01
    • 2011-04-22
    • 1970-01-01
    • 2016-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多