gpt4 book ai didi

c++ - 仅在(互斥)requires-clauses : legal or an ODR-violation? 中通过差异重载隐藏的 friend

转载 作者:行者123 更新时间:2023-12-03 06:49:43 32 4
gpt4 key购买 nike

考虑下面的类模板,它包含同一个 friend (相同的函数类型;见下文)的两个(隐藏) friend 声明,它也定义了 friend (因此 friend 是内联的),但定义条件为(互斥) 要求条款:

#include <iostream>

struct Base {};

template<int N>
struct S : public Base {
friend int foo(Base&) requires (N == 1) { return 1; }
friend int foo(Base&) requires (N == 2) { return 3; }
};
[dcl.fct]/8声明尾部的 requires 子句不是函数类型的一部分 [ 重点 矿]:

The return type, the parameter-type-list, the ref-qualifier, the cv-qualifier-seq, and the exception specification, but not the default arguments ([dcl.fct.default]) or the trailing requires-clause ([dcl.decl]), are part of the function type.


这意味着对于两个定义都被实例化的情况,上述两个定义违反了 ODR;如果我们只关注一个翻译单元, [basic.def.odr]/1会违反:

No translation unit shall contain more than one definition of any variable, function, class type, enumeration type, template, default argument for a parameter (for a function in a given scope), or default template argument.


并且在单个 TU 中,这种违规行为应该可以被诊断出来(不需要“格式错误,NDR”)。我正在尝试了解何时实例化上述定义的规则;或者如果这完全是实现定义的(或者甚至在到达实例化阶段之前格式不正确)。
Clang 和 GCC(1) 都接受以下程序
// ... as above

// (A)
int main() {
S<1> s1{};
std::cout << foo(s1); // Clang & GCC: 1
}
然而,对于下面的程序 (B) 到 (D),Clang 接受它们,而 GCC 拒绝它们,并出现重新定义错误:
// (B)
int main() {
S<1> s1{};
S<2> s2{}; // GCC: re-definition error of 'foo'
}

// (C)
int main() {
S<1> s1{};
S<2> s2{}; // GCC: re-definition error of 'foo'
std::cout << foo(s1); // Clang: 1
}

// (D)
template struct S<1>;
template struct S<2>; // GCC: re-definition error of 'foo'

int main() {}
只有当实际尝试通过 ADL 在两个特化上调用 friend 函数时,Clang 才会实际发出错误
// (E)
int main() {
S<1> s1{};
S<2> s2{}; // GCC: re-definition error of 'foo'
std::cout << foo(s1); // MSVC: ambiguous call
std::cout << foo(s2);
// Clang error: definition with same mangled name
// '_Z3fooR4Base' as another definition
}
并且我们可能会注意到,只有 MSVC 实际上达到了看似接受这两个定义的状态,然后它按预期失败(“模棱两可的调用”)。
DEMO .

  • 类模板的隐藏非模板友元函数(友元声明在类中也定义了友元)是否可以仅通过(互斥)requires-clause 中的差异重载?

  • 而且,因此,哪个编译器就在这里?
  • 所有(格式错误的 NDR 和/或实现定义 w.r.t. 实例化点),
  • 海合会
  • 叮当
  • MSVC
  • 无(示例 (E) 格式良好)

  • 我一直无法理解什么规则控制了 friend 函数声明(类模板的)也是一个定义,被实例化,特别是当涉及到 requires 子句时;不过,如果上述 GCC 和 Clang 的行为都不正确,则这可能无关紧要。

    (1) GCC HEAD 11.0.0,Clang HEAD 12.0.0。

    最佳答案

    来自 over#dcl-1 ,

    Two function declarations of the same name refer to the same function if they are in the same scope and have equivalent parameter declarations ([over.load]) and equivalent ([temp.over.link]) trailing requires-clauses, if any ([dcl.decl]).


    [Note 1: Since a constraint-expression is an unevaluated operand, equivalence compares the expressions without evaluating them.
    [Example 1:
    template<int I> concept C = true;
    template<typename T> struct A {
    void f() requires C<42>; // #1
    void f() requires true; // OK, different functions
    };
    — end example]
    — end note]


    我知道有 2 种不同的 foo (因此不会违反 ODR),因为需要不同的条款。
    我认为所有提到的编译器都存在问题,无法涵盖这种极端情况。

    关于c++ - 仅在(互斥)requires-clauses : legal or an ODR-violation? 中通过差异重载隐藏的 friend ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64758699/

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