在 class 模板的 non-defined 成员 class 的显式特化中定义隐藏好友是否合法?
Is it legal to define a hidden friend in an explicit specialization of an otherwise non-defined member class of a class template?
根据 [temp.expl.spec] are not entirely easy to grasp, particularly when mixing with hidden friends, so as to avoid the immolation[temp.expl.spec]/8 我的专业化和友元函数的显式专业化的合法放置规则 我希望获得第二意见(1)以下:
- 在 class 模板的 header 文件中定义一个隐藏的朋友在其他 non-defined(/仅声明)成员的显式特化中是否合法=46=] class 模板?假设这个 header 包含在至少两个不同的翻译单元中。
(1) 我自己对标准的解释是,根据下面的标准参考,答案是“是的;这是合法的”。
或者,举个例子:下面的程序是well-formed?
// 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();
}
请注意,如果我们将 S<42>::M
视为“只是”一个 class 类型,则根据 [class.friend]/7, so whilst I'm somewhat worried about ODR-violations it is not for the friend but rather for the member class specialization. I think [basic.def.odr]/6 在其好友声明中定义的好友是内联的。
Clang 和 GCC 都接受上述内容,但如果程序是 ill-formed NDR 或具有未定义的行为,这可能并不重要。 GCC 10.1.0 DEMO, Clang 10.0.0 DEMO.
是的,模板化 class(包括 class 模板和 class 模板的成员 classes)的显式特化是 class , 因此在通常情况下允许多个定义。这些定义被视为程序中只有 one,因此 f
也可以。 (不清楚 implicit inline
在这里做了什么,因为 f
只有一个定义,以至于整个 S<42>::M
只有一个。) S<N>::M
的定义在这里意味着什么;像这样的“成员显式特化”实际上是 enclosingclass 模板 S
的缩写特化,因此 S<42>::M
完全不相关。
根据 [temp.expl.spec] are not entirely easy to grasp, particularly when mixing with hidden friends, so as to avoid the immolation[temp.expl.spec]/8 我的专业化和友元函数的显式专业化的合法放置规则 我希望获得第二意见(1)以下:
- 在 class 模板的 header 文件中定义一个隐藏的朋友在其他 non-defined(/仅声明)成员的显式特化中是否合法=46=] class 模板?假设这个 header 包含在至少两个不同的翻译单元中。
(1) 我自己对标准的解释是,根据下面的标准参考,答案是“是的;这是合法的”。
或者,举个例子:下面的程序是well-formed?
// 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();
}
请注意,如果我们将 S<42>::M
视为“只是”一个 class 类型,则根据 [class.friend]/7, so whilst I'm somewhat worried about ODR-violations it is not for the friend but rather for the member class specialization. I think [basic.def.odr]/6 在其好友声明中定义的好友是内联的。
Clang 和 GCC 都接受上述内容,但如果程序是 ill-formed NDR 或具有未定义的行为,这可能并不重要。 GCC 10.1.0 DEMO, Clang 10.0.0 DEMO.
是的,模板化 class(包括 class 模板和 class 模板的成员 classes)的显式特化是 class , 因此在通常情况下允许多个定义。这些定义被视为程序中只有 one,因此 f
也可以。 (不清楚 implicit inline
在这里做了什么,因为 f
只有一个定义,以至于整个 S<42>::M
只有一个。) S<N>::M
的定义在这里意味着什么;像这样的“成员显式特化”实际上是 enclosingclass 模板 S
的缩写特化,因此 S<42>::M
完全不相关。