使用私有内部类作为模板参数默认值(gcc 与 clang)

Using a private inner class as template parameter default value (gcc vs clang)

提问人:many-sigsegv 提问时间:7/5/2023 更新时间:7/6/2023 访问量:55

问:

我使用(简化的)以下代码来实现 pimpl 成语

// in .h
#include <memory>
template<class T, class Impl = typename T::Impl> class Pimpl {
public:
    Pimpl() : m_impl(std::make_unique<Impl>()) {}
    Impl * operator->() { return m_impl.get(); }
    const std::unique_ptr<Impl> m_impl;
};

class MyClass {
public:
    int getData();
private:
    class Impl;
    Pimpl<MyClass> m_impl;
};

// in .cpp
class MyClass::Impl {
public:
    int data = 1;
};

int MyClass::getData() {
    return m_impl->data;
}

int main() {
    MyClass c;
    return c.getData();
}

它适用于 g++,但使用 clang++ 构建会导致错误

error: 'Impl' is a private member of 'MyClass'
template<class T, class Impl = typename T::Impl> class Pimpl
                                           ^

这似乎是合理的,但是如果我在 MyClass 中替换 by,那么 clang++ 构建没有问题,并在 Pimpl::P impl() 中愉快地创建一个“private”类的实例。Pimpl<MyClass> m_impl;Pimpl<MyClass, Impl> m_impl;

那么使用私有内部类作为模板参数默认值是否是一种有效的行为(并且 clang 存在问题)?还是被禁止(gcc 太宽松了)?还是没有指定?

这个问题,如何在模板专用化中使用私有内部模板类作为参数? 是相似的,但上下文(模板专业化)和答案(“模板从未实际实例化”)在这里似乎无关紧要。

使用 clang 10.0.0 和 gcc 9.4.0 进行测试。代码使用 c++17。

C++ 模板 访问说明符

评论


答:

0赞 Nimrod 7/6/2023 #1

我相信 clang 符合这里的标准。根据 [temp.arg]/3

模板参数的名称应在用作模板参数时可访问。...对于作为类类型或类模板的模板参数,模板定义对模板参数的成员没有特殊的访问权限。

内部的隐式实例化实际上是无效的。Pimpl<MyClass, MyClass::Impl>MyClass