콘텐츠로 이동

C++23 Deducing This (explicit object parameter)

C++23의 explicit object parameter는 멤버 함수의 암묵적 this명시적 파라미터로 선언하는 기능입니다. 이를 통해 this의 타입을 템플릿으로 추론할 수 있습니다.

struct Widget {
// 기존: 암묵적 this
void paint_old() { /* this는 Widget* */ }
// C++23: 명시적 object parameter
void paint(this Widget& self) { /* self는 Widget& */ }
void paint(this const Widget& self) const { /* const 버전 */ }
};

기존에는 const/non-const 오버로드를 둘 다 작성해야 했습니다.

// C++20 이전: 두 개 필요
class Container {
std::vector<int> data_;
public:
int& at(size_t i) { return data_[i]; }
const int& at(size_t i) const { return data_[i]; }
};
// C++23: 하나로 통합
class Container {
std::vector<int> data_;
public:
auto& at(this auto& self, size_t i) {
return self.data_[i]; // self가 const면 const int& 반환
}
};

기존 람다는 자기 자신을 참조할 수 없었습니다. Deducing this로 해결됩니다.

// C++23: 재귀 람다
auto fibonacci = [](this auto self, int n) -> int {
if (n <= 1) return n;
return self(n - 1) + self(n - 2);
};
std::cout << fibonacci(10); // 55

기존 CRTP 패턴을 더 간결하게 표현할 수 있습니다.

// 기존 CRTP
template<typename Derived>
class Base {
void interface() {
static_cast<Derived*>(this)->implementation();
}
};
// C++23 Deducing This
struct Base {
void interface(this auto& self) {
self.implementation(); // 실제 타입의 implementation() 호출
}
};
struct Derived : Base {
void implementation() { puts("Derived"); }
};
Derived d;
d.interface(); // "Derived" 출력

파생 클래스에서도 체이닝이 끊기지 않습니다.

struct Builder {
int x = 0, y = 0;
auto& setX(this auto& self, int v) {
self.x = v;
return self; // 실제 타입 반환
}
auto& setY(this auto& self, int v) {
self.y = v;
return self;
}
};
struct DerivedBuilder : Builder {
int z = 0;
auto& setZ(this auto& self, int v) {
self.z = v;
return self;
}
};
DerivedBuilder b;
b.setX(1).setY(2).setZ(3); // 기존 CRTP 없이도 체이닝 유지
struct Obj {
std::string data;
// ref qualifier 세 버전을 하나로
decltype(auto) get(this auto&& self) {
return std::forward_like<decltype(self)>(self.data);
}
};
Obj o{"hello"};
const Obj co{"world"};
std::string& r1 = o.get(); // lvalue ref
const std::string& r2 = co.get(); // const lvalue ref
std::string moved = Obj{"!!"}.get(); // rvalue — 이동
컴파일러지원 버전
GCC14+
Clang18+
MSVCVS 2022 17.7+
  • this auto& selfthis를 명시적으로 받아 const/non-const 중복 제거
  • 재귀 람다를 간결하게 표현 가능
  • CRTP의 복잡한 캐스팅 없이 정적 다형성 구현
  • 빌더 패턴에서 파생 클래스도 체이닝이 자연스럽게 유지