반영 연산자 (C++26부터)
cppreference.net에서
단항 ^^ 연산자, 반영 연산자라고 불리며, 주어진 언어 구문의 반영을 std::meta::info 타입으로 생성합니다.
구문
^^ ::
|
(1) | ||||||||
^^ 반영 이름
|
(2) | ||||||||
^^ 타입 식별자
|
(3) | ||||||||
^^ 식별 표현식
|
(4) | ||||||||
| 반영 이름 | - | 식별자, 선택적으로 한정됨, 선택적으로 템플릿 명확화 사용. 이 형식은 타입 식별자 및 식별 표현식 |
| 보다 우선합니다.타입 식별자 | - | a 타입 식별자 |
| 식별 표현식 | - | a 식별 표현식 |
구문적으로 ^^의 피연산자가 될 수 있는 가장 긴 토큰 시퀀스가 파싱됩니다. 결과가 템플릿을 나타내는 경우 표현식 바로 뒤에 <가 오면 안 됩니다.
static_assert(std::meta::is_type(^^int())); // ^^int() represents the type int()
// not a function call to ^^int
template<bool> struct X {};
consteval bool operator<(std::meta::info, X<false>) { return false; }
consteval void g(std::meta::info r, X<false> xv) {
r == ^^int && true; // error: ^^ applies to the type-id int&&
r == ^^int & true; // error: ^^ applies to the type-id int&
r == (^^int) && true; // OK
r == ^^int &&&& true; // error: int &&&& is not a valid type-id
^^X < xv; // error: reflect-expression that represents a template is followed by <
(^^X) < xv; // OK
^^X<true> < xv; // OK
}
설명
1) 표현식
^^::은 전역 네임스페이스를 나타냅니다.2)
^^reflection-name에서 반영 이름이 조회되며, 표현은 다음과 같이 결정됩니다:
- 조회가 사용 선언자를 대체한 선언을 찾으면, 표현식은 유효하지 않습니다.
- 그렇지 않고, 조회가 네임스페이스 별칭, 네임스페이스, 또는 개념을 찾으면, 결과는 해당 엔티티를 나타냅니다.
- 그렇지 않고, 조회가 템플릿을 찾으면:
- 조회가 주입 클래스 이름을 찾으면:
- 템플릿 명확화가 있으면, 결과는 주입 클래스 이름이 명명한 클래스 템플릿을 나타냅니다.
- 그렇지 않으면, 주입 클래스 이름은 타입 이름으로 간주할 때 모호하지 않아야 합니다(그렇지 않으면 표현식은 유효하지 않습니다). 결과는 그렇게 명명된 타입을 나타냅니다.
- 그렇지 않고, 조회가 타입 템플릿 매개변수를 찾으면, 결과는 해당 인자의 타입을 나타냅니다.
- 그렇지 않고, 조회가 typedef 이름 또는 타입 별칭을 찾으면, 결과는 해당 타입 별칭을 나타냅니다.
template<typename T>
struct S {
static constexpr std::meta::info r = ^^T;
using type = T;
};
static_assert(S<int>::r == ^^int); // OK
static_assert(^^S<int>::type != ^^int); // OK
typedef struct X {} Y;
typedef struct Z {} Z;
constexpr std::meta::info e = ^^Y; // OK, represents the type alias Y
constexpr std::meta::info f = ^^Z; // OK, represents the type alias Z, not the type
3) 표현식
^^type-id은 다음과 같이 결정된 엔티티를 나타냅니다:
4) 표현식
^^id-expression은 다음과 같이 결정된 엔티티를 나타냅니다:
- 식별 표현식이 다음을 나타내면:
- 람다의 초기화 캡처로 선언된 변수,
- 함수 지역 미리 정의 변수 (
__func__), - 지역 매개변수 (
requires식으로 선언됨), 또는 - 도입된 지점과 반영 표현식 사이에 람다 범위가 개입된 지역 엔티티 (엔티티가 캡처되었는지 여부와 관계없이),
- 표현식은 유효하지 않습니다.
- 그렇지 않고, 식별 표현식이 오버로드 집합을 나타내면, 오버로드 해결이 고유한 함수를 선택해야 합니다. 결과는 해당 함수를 나타냅니다.
template<typename T> void fn() requires (^^T != ^^int);
template<typename T> void fn() requires (^^T == ^^int);
template<typename T> void fn() requires (sizeof(T) == sizeof(int));
constexpr std::meta::info a = ^^fn<char>; // OK
constexpr std::meta::info b = ^^fn<int>; // error: ambiguous
- 그렇지 않고, 식별 표현식이 변수, 구조적 바인딩, 열거자, 또는 비정적 데이터 멤버를 나타내면, 결과는 해당 엔티티를 나타냅니다.
- 그렇지 않으면 (예를 들어 식별 표현식이 비타입 템플릿 매개변수 또는 팩 인덱싱 표현식을 나타내는 경우), 표현식은 유효하지 않습니다.
피연산자는 평가되지 않은 피연산자입니다.
참고
반영 값은 std::meta::reflect_constant, std::meta::reflect_object, std::meta::reflect_function, 또는 기본 초기화 std::meta::info로도 생성할 수 있습니다. 또한, 기존 <std::meta::info> 객체로 메타 함수를 호출하여 반영 값을 얻을 수 있습니다.
타입 별칭이 타입 식별자의 일부로 나타나는 경우, 반영 연산자는 타입 별칭을 보존하지 않습니다.
using T = int;
static_assert(^^T != ^^int);
static_assert(^^T& == ^^int&);
static_assert(^^T const == ^^const int);
예제
이 코드 실행
int arr[] = {1, 2, 3};
auto [a1, a2, a3] = arr;
[[=1]] void fn(int n);
enum Enum { A };
using Alias = int;
struct S { int mem; };
template<auto> struct TCls {};
template<auto> void TFn();
template<auto> int TVar;
template<auto N> using TAlias = TCls<N>;
template<auto> concept Concept = true;
namespace NS {}
namespace NSAlias = NS;
constexpr auto r_arr = ^^arr; // represents a variable
constexpr auto r_sb = ^^a3; // represents a structured binding
constexpr auto r_fn = ^^fn; // represents a function
constexpr auto r_enum = ^^Enum::A; // represents an enumerator
constexpr auto r_alias = ^^Alias; // represents a type alias
constexpr auto r_type = ^^S; // represents a type
constexpr auto r_mem = ^^S::mem; // represents a class member
constexpr auto r_tcls = ^^TCls; // represents a class template
constexpr auto r_tfn = ^^TFn; // represents a function template
constexpr auto r_tvar = ^^TVar; // represents a variable template
constexpr auto r_ttype = ^^TAlias; // represents an alias template
constexpr auto r_cncpt = ^^Concept; // represents a concept
constexpr auto r_ns = ^^NS; // represents a namespace
constexpr auto r_ns2 = ^^NSAlias; // represents a namespace alias
int main() {}
같이 보기
(C++26) |
값 또는 템플릿 매개변수 객체를 나타내는 반영을 반환하며, 상수 템플릿 인자로 사용하기 적합함 (함수 템플릿) |
(C++26) |
객체를 나타내는 반영을 반환하며, 상수 템플릿 인자로 사용하기 적합함 (함수 템플릿) |
(C++26) |
함수를 나타내는 반영을 반환하며, 상수 템플릿 인자로 사용하기 적합함 (함수 템플릿) |