cpp core · advanced

Two-Phase Lookup: Why a Dependent Base's Member Won't Compile

Asked at Trading Technologies. A class template that inherits from a dependent base (Derived<T> : Base<T>) cannot see the base's members through an unqualified call. C++ uses two-phase name lookup: non-dependent names - like a no-argument, unqualified data() - are bound in phase 1 at definition time, when the compiler refuses to look inside Base<T> because a later specialization could change or remove its members. Make the name dependent so lookup is deferred to phase 2 (instantiation): this->data() (implicit this is dependent), Base<T>::data() (explicit qualification), or add using Base<T>::data; in the class body.

🔑 Key line

In Derived<T> : Base<T>, an unqualified data() is a non-dependent name resolved in phase 1 - which never searches the dependent base. Fix with this->data(), Base<T>::data(), or using Base<T>::data;.

The code

#include <iostream>
template <typename T>
struct Base {
void data() { std::cout << "Base::data()\n"; }
};
template <typename T>
struct Derived : Base<T> { // Base<T> is a DEPENDENT base (it depends on T)
void execute() {
// data(); // (1) ERROR: 'data' was not declared in this scope
this->data(); // (2) Fix 1 - 'this->' makes the name dependent
// Base<T>::data(); // (3) Fix 2 - qualify with the base class
// using Base<T>::data; // (4) Fix 3 - a using-declaration in the class body
}
};
int main() {
Derived<int> obj;
obj.execute(); // prints: Base::data()
}

What this lesson walks through

  1. 01Looks obvious - and it won't compile
  2. 02Templates compile in TWO phases
  3. 03Phase-1 lookup skips the dependent base
  4. 04Why the standard forbids the shortcut
  5. 05Fix 1 - this-> defers the lookup
  6. 06Three one-line fixes

Derived<int> inherits Base<int>, Base defines data(), and execute() just calls data(). Intuition says the call is found. The compiler says: 'data' was not declared in this scope. The reason is how templates are name-looked-up.

See it animated — step by step, at your own pace

Unlock the full interactive walkthrough of Two-Phase Lookup: Why a Dependent Base's Member Won't Compile and 100+ animated C++ interview lessons.

← Previous
C Fundamentals: Struct Padding, Union, Bit Fields, alignas, Pointer Arithmetic
Next →
Argument-Dependent Lookup (ADL / Koenig Lookup)