当前位置: 首页 > 知识库问答 >
问题:

只在(互斥的)要求条款中通过差异过载隐藏的朋友:合法还是违反ODR?

邓驰
2023-03-14

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

#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子句不是函数类型的一部分[强调项]:

返回类型、参数-type-list、ref-qualifier、cv-qualifier-seq和异常规范(而不是默认参数([dcl.fct.default])或尾随的requires子句([dcl.decl])是函数类型的一部分。

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

任何翻译单元不得包含任何变量、函数、类类型、枚举类型、模板、参数的默认参数(对于给定作用域中的函数)或默认模板参数的一个以上定义。

在单个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实际上达到了似乎接受这两个定义的状态,然后它就像预期的那样失败了(“模棱两可的调用”)。

演示。

    null
    null

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

(1)GCC HEAD 11.0.0,Clang HEAD 12.0.0.

共有1个答案

鲁钱明
2023-03-14

从#DCL-1以上,

如果两个相同名称的函数声明位于相同的作用域中,并且在requires-子句后面有等效的参数声明([over.load])和等效的([temp.over.link])(如果有)([dcl.decl]),则引用相同的函数。

[注意1:由于约束表达式是未求值的操作数,因此等效性不求值就比较表达式。
[示例1:
模板 概念C=true;
模板 结构a{
void f()要求C<42>;//#1
};
};
-结束示例]
-结束注意]

我知道有两个不同的foo(所以没有ODR冲突),因为requires子句不同。

我认为所有提到的编译器都有问题,不能涵盖这个角落的情况。

 类似资料:
  • 为了了解在朋友关系中使用Neo4J的优势,我在MySQL数据库上创建了一个Persons表(“Persons”,20900个数据集): 和一张关系表(“友谊”,每个人有50到100个朋友): 因此,大约有120万人的关系。 现在我想查看id=1的人的朋友的朋友的朋友的朋友,因此我创建了一个如下查询: 用户ID 1的查询用了大约30秒 在Neo4J中,我为每个人创建了一个节点(20900个节点)和一

  • 问题内容: 我有这个问题。给定一个包含社交网络中用户名和用户名的表,该表包含用户名和用户的朋友名,如下所示… …我正在尝试编写一条SQL语句,如果用户在我的网络中,它将执行此操作。换句话说,该用户是朋友还是朋友的朋友? 我一直在围绕这个问题跳舞,只能提出以下查询: 它基本上检查用户是否是我朋友的朋友,即如果为false则仅返回null。 试图弄清楚如何扩展才能遍及我的所有朋友网络。我的意思不仅是我

  • 问题内容: 我有一个类似于myspace / facebook的社交网络。在我的代码中,您不是一个人的朋友,还是不是一个朋友,因此,我显示了您与之成为朋友的人的所有操作(在此帖子中,我将这些操作单独称为公告帖子,以使其更易于可视化。 因此,您每当有人发布公告时,都会向在那里的任何朋友显示。 在mysql中,您可以通过执行以下操作来获得个人朋友列表, 我想知道像facebook之类的网站如何显示您的

  • 问题内容: 我正在研究“可能的朋友”功能。在这里,我需要向不是我的朋友的所有朋友显示所有朋友,也不要发送给我或没有我的待处理请求 对于每一次友谊,我都会做两个记录。假设用户1和2成为朋友…我要在表中做一个记录,再做一个。 当第一个用户发送请求时,将状态设置为0,而当朋友接受请求时,我将两行都更新为1 如何根据朋友的朋友进行建议“可能的朋友”的sql查询? 问题答案: 在这里,您…简单加入

  • 因此,我正在开发一个应用程序,其中使用访问令牌(JWT,使用Spring Security)对用户进行身份验证,令牌被加密并存储在httponly cookie(ngx-cookie)中,访问令牌的有效期为24小时,如果过期则会发出新令牌,目前我正在开发localhost并且每当我进行api调用时,承载令牌都会在网络选项卡的标头中可见。我的问题是,当应用程序处于活动状态并且通过https(SSL)

  • 我已经在购物车页面上隐藏了优惠券字段。现在,我尝试隐藏或显示优惠券字段,具体取决于结帐页面上的付款方式。 我尝试了这个代码:在结账页面中检测WooCommerce付款方式 但这行不通。你有什么提示给我吗。谢谢