【C++】在使用PImpl技术时,template/typename的不常见用法

PImpl:Pointer to implementation,常用于隐藏实现细节,构造拥有稳定 ABI 的 C++ 库接口,及减少编译时依赖。

在使用pimpl技术时,pimpl是类静态变量,对其在源文件中的实现需要使用typename关键字

对于模板类的静态成员变量的定义,你需要使用完整的模板类型限定符来指定 std::unique_ptr 的类型。在这个示例中,我们使用 typename MyClass<T>::Impl 来指定 std::unique_ptr 的类型。

// MyClass.h

#include <memory>

template<typename T>
class MyClass {
public:
    void doSomething();

private:
    class Impl;
    static std::unique_ptr<Impl> p_impl;  // 静态 p_impl 变量的声明
};

// MyClass.cpp

template<typename T>
class MyClass<T>::Impl {
public:
    void doSomething() {
        // 实现具体逻辑
        std::cout << "Doing something..." << std::endl;
    }
};

template<typename T>
std::unique_ptr<typename MyClass<T>::Impl> MyClass<T>::p_impl = std::make_unique<typename MyClass<T>::Impl>();  // 静态 p_impl 变量的定义

template<typename T>
void MyClass<T>::doSomething() {
    p_impl->doSomething();
}

如果一个模板类使用p_impl技术,同时内部包含模板函数,那么模板函数的调用需要额外使用template关键字

在最后的代码p_impl->template doSomething<U>();处,使用template关键字告诉编译器我们正在引用一个模板成员函数doSomething<U>()。不使用template关键字会报错

// MyClass.h

#include <memory>

template<typename T>
class MyClass {
public:
    MyClass();
    template<typename U>
    void doSomething();

private:
    class Impl;
    std::unique_ptr<Impl> p_impl;
};

// MyClass.cpp

template<typename T>
class MyClass<T>::Impl {
public:
    template<typename U>
    void doSomething() {
        // 实现具体逻辑
        std::cout << "Doing something with type " << typeid(U).name() << "..." << std::endl;
    }
};

template<typename T>
MyClass<T>::MyClass() : p_impl(std::make_unique<Impl>()) {}

template<typename T>
template<typename U>
void MyClass<T>::doSomething() {
    p_impl->template doSomething<U>();
}
posted @ 2023-05-15 01:09  缙云烧饼  阅读(133)  评论(0编辑  收藏  举报