c++ - 在类模板的其他未定义成员类的显式特化中定义隐藏 friend 是否合法?

标签 c++ templates language-lawyer template-specialization friend

根据 [temp.expl.spec] 的明确特化的合法安置规则不是很容易掌握,尤其是和隐藏的 friend 混在一起的时候,以免自焚[temp.expl.spec]/8关于我的专业和 friend 功能,我希望对以下内容有第二意见 (1):

  • 在类模板的头文件中,在类模板的其他未定义(/仅声明)成员类的显式特化中定义隐藏 friend 是否合法?假设该报头包含在至少两个不同的翻译单元中。

  • (1) 根据以下标准引用资料,我自己对标准的解释是“是的;这是合法的”。

    或者,举个例子:下面的程序格式正确吗?
    // s.h
    #pragma once
    
    template <int N>
    struct S {
        struct M;
    };
          
    template<>
    struct S<42>::M {
        friend int f(M) { return 42; }
    };
    
    // foo.h
    #pragma once
    void foo();
    
    // foo.cpp
    #include "foo.h"
    #include <iostream>
    #include "s.h"
    
    void foo() {
        std::cout << f(S<42>::M{});
    }
    
    // main.cpp
    #include <iostream>
    #include "foo.h"
    #include "s.h"
    
    int main() {
        std::cout << f(S<42>::M{});
        foo();
    }
    
    请注意,根据 [class.friend]/7,在其 friend 声明中定义的 friend 是内联的。 ,所以虽然我有点担心 ODR 违规,但它不是针对 friend ,而是针对成员类特化。我想 [basic.def.odr]/6如果我们考虑 S<42>::M,此处适用作为“只是”一个类类型。

    Clang 和 GCC 都接受上述内容,但如果程序格式不正确或具有未定义的行为,这可能并不重要。 GCC 10.1.0 DEMO , Clang 10.0.0 DEMO .

    最佳答案

    是的,模板化类(包括类模板和类模板的成员类)的显式特化是一个类,因此在通常情况下允许多个定义。这些定义被视为只有 在程序中,所以 f也可以。 (不清楚隐式 inline 在这里做什么,因为 f 只有一个定义,以至于 S<42>::M 整体上只有一个。) S<N>::M 的定义缺失也没有在这里意味着什么;像这样的“成员显式特化”实际上是 的缩写特化附 类模板S ,所以 S<42>::M是完全无关的。

    关于c++ - 在类模板的其他未定义成员类的显式特化中定义隐藏 friend 是否合法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64955776/

    相关文章:

    c++ - 使用 lambda 的多映射谓词

    c++ - C++ 中的通用参数检查器

    c++ - Mongodb C++11 API errno 干扰

    c++ - C++11 标准中的 §12.3.2/1 似乎存在矛盾

    c - 重复 printf 说明符标志时的行为是什么?

    c++ - 调用静态方法

    c++ - 类模板上的关系运算符

    templates - 如何更改 Android Studio 用于创建空白事件的模板

    templates - 在 Knockout.js 中使用 foreach 绑定(bind)而不更改上下文

    c++ - 命名空间作用域在 C++ 中是如何工作的?