提问人:many-sigsegv 提问时间:7/5/2023 更新时间:7/6/2023 访问量:55
使用私有内部类作为模板参数默认值(gcc 与 clang)
Using a private inner class as template parameter default value (gcc vs clang)
问:
我使用(简化的)以下代码来实现 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。
答:
0赞
Nimrod
7/6/2023
#1
我相信 clang 符合这里的标准。根据 [temp.arg]/3,
模板参数的名称应在用作模板参数时可访问。...对于作为类类型或类模板的模板参数,模板定义对模板参数的成员没有特殊的访问权限。
内部的隐式实例化实际上是无效的。Pimpl<MyClass, MyClass::Impl>
MyClass
评论