friend 注入会是病态的吗?
Will friend injections be ill-formed?
曾经在standard中有一段说
the names of a namespace-scope friend functions of a class template specialization are not visible during an ordinary lookup unless explicitly declared at namespace scope. Such names may be found under for associated classes.
template <typename T> struct number {
number(int);
friend number gcd(number x, number y) { return 0; }
};
void g() {
number<double> a(3), b(4);
a = gcd(a, b); // finds gcd becuase numer<double> is an associated class,
// making gcd visible in its namespace (global scope)
b = gcd(3, 4); // error: gcd is not visible
}
此功能已用于在编译时捕获和检索元编程状态。
template <int X>
struct flag {
friend consteval int f(flag<X>);
};
template <int X, int N>
struct injecter {
friend consteval int f(flag<X>) { return N; }
};
template <int N = 0, auto = []{}>
consteval auto inject() {
if constexpr (requires { f(flag<X>{}); }) {
return inject<N+1>();
} else {
void(injecter<X>{});
return f(flag<X>{});
}
}
static_assert(inject() == 0);
static_assert(inject() == 1);
static_assert(inject() == 2);
static_assert(inject() == 3);
// ...
据我所知,CWG 有一个 issue 旨在使此类行为成为错误的行为,尽管禁止它们的机制尚未确定。但是,由于最新草案中似乎没有该段落,我想知道友元注入在 C++23 中是否格式错误。
来自P1787R6:
Merged [temp.inject] into [temp.friend]
(2021 年 3 月 N4885 通过)
当前草案 (N4901) 为 ([temp.friend]p2):
Friend classes, class templates, functions, or function templates can be declared within a class template.
When a template is instantiated, its friend declarations are found by name lookup as if the specialization had
been explicitly declared at its point of instantiation
里面好像覆盖了旧的[temp.inject]p2
曾经在standard中有一段说
the names of a namespace-scope friend functions of a class template specialization are not visible during an ordinary lookup unless explicitly declared at namespace scope. Such names may be found under for associated classes.
template <typename T> struct number {
number(int);
friend number gcd(number x, number y) { return 0; }
};
void g() {
number<double> a(3), b(4);
a = gcd(a, b); // finds gcd becuase numer<double> is an associated class,
// making gcd visible in its namespace (global scope)
b = gcd(3, 4); // error: gcd is not visible
}
此功能已用于在编译时捕获和检索元编程状态。
template <int X>
struct flag {
friend consteval int f(flag<X>);
};
template <int X, int N>
struct injecter {
friend consteval int f(flag<X>) { return N; }
};
template <int N = 0, auto = []{}>
consteval auto inject() {
if constexpr (requires { f(flag<X>{}); }) {
return inject<N+1>();
} else {
void(injecter<X>{});
return f(flag<X>{});
}
}
static_assert(inject() == 0);
static_assert(inject() == 1);
static_assert(inject() == 2);
static_assert(inject() == 3);
// ...
据我所知,CWG 有一个 issue 旨在使此类行为成为错误的行为,尽管禁止它们的机制尚未确定。但是,由于最新草案中似乎没有该段落,我想知道友元注入在 C++23 中是否格式错误。
来自P1787R6:
Merged [temp.inject] into [temp.friend]
(2021 年 3 月 N4885 通过)
当前草案 (N4901) 为 ([temp.friend]p2):
Friend classes, class templates, functions, or function templates can be declared within a class template. When a template is instantiated, its friend declarations are found by name lookup as if the specialization had been explicitly declared at its point of instantiation
里面好像覆盖了旧的[temp.inject]p2