Механизм шаблонов C++, при котором ошибка подстановки типа не приводит к ошибке компиляции, а просто исключает перегрузку из consideration set.
template<typename T>
auto has_foo_impl(int) -> decltype(std::declval<T>().foo(), std::true_type{});
template<typename T>
std::false_type has_foo_impl(...);
template<typename T>
constexpr bool has_foo = decltype(has_foo_impl<T>(0))::value;
template<typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
void process(T value) { /* для целых чисел */ }
template<typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
void process(T value) { /* для чисел с плавающей точкой */ }
template<typename T>
auto begin(T& t) -> decltype(t.begin()) { return t.begin(); }
// Заголовочный файл (публичный интерфейс)
class Widget {
public:
Widget();
```Widget();
void publicMethod();
private:
struct Impl; // Предварительное объявление
std::unique_ptr<Impl> pImpl;
};
// Файл реализации
struct Widget::Impl {
void privateMethod() { /* ... */ }
int privateData;
};
Widget::Widget() : pImpl(std::make_unique<Impl>()) {}
Widget::```Widget() = default; // Необходим для unique_ptr
void Widget::publicMethod() { pImpl->privateMethod(); }
Критерий | SFINAE | PIMPL |
---|---|---|
Назначение | Метапрограммирование | Сокрытие реализации |
Влияние на ABI | Нет | Да (стабильность интерфейса) |
Производительность | Нулевые накладные расходы | Косвенный доступ |
Сложность | Высокая (шаблоны) | Средняя |
SFINAE:
PIMPL:
Обе техники важны для профессионального C++ разработчика, но в современном C++ (20/23) SFINAE постепенно вытесняется концептами, а PIMPL остается актуальным для стабильных API.