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