考虑代码:
#include <memory>
template <class T, class Deleter = std::default_delete<T>>
class unique_ptr_wrapper: public std::unique_ptr<T, Deleter>
{
public:
using typename std::unique_ptr<T, Deleter>::unique_ptr;
operator T* () const {return this->get();}
};
int main()
{
unique_ptr_wrapper<int> upw{new int{42}};
}
尽管clang ++抱怨,但是g ++ 5.1编译得很好
错误:仅允许使用typename
我同意我们这里没有标识符,因此可能不需要typename
。但它真的被禁止了吗?是否需要编译器至少发出诊断信息?
编辑 g ++和clang ++都没有typename
编译好代码。
更新这似乎是一个g ++错误,我报告了它here。
答案 0 :(得分:8)
[class.inhctor] / p1,强调我的:
using-declaration (7.3.3)隐含地命名构造函数 声明一组继承构造函数。
构造函数不是类型。
[temp.res] / P3-4:
3当 qualified-id 旨在引用不是a的类型时 当前实例化的成员(14.6.2.1)及其成员 nested-name-specifier 是指依赖类型,它应以关键字
typename
作为前缀,形成一个typename-specifier。如果 typename-specifier 中的 qualified-id 不表示类型, 该计划格式不正确。4如果为一组实例化实例化模板的特化 template-arguments ,以
typename
为前缀的 qualified-id 不表示类型,专业化不正确。 通常的限定名称查找(3.4.3)用于查找 qualified-id 即使存在typename
。
[class.qual] / P2:
在查找中,不忽略函数名称和 nested-name-specifier 指定一个类
C
:
如果在
C
中查找 nested-name-specifier 之后指定的名称,则是的注入类名称C
(第9条)或在 using-declaration (7.3.3) member-declaration 中,如果在嵌套名称后指定的名称 - 说明符与...相同 标识符或 simple-template-id 的模板名称 嵌套名称说明符的最后一个组件,
而是将名称视为命名类
C
的构造函数。
应用[class.qual]中的“通常限定名称查找”规则,std::unique_ptr<T, Deleter>::unique_ptr
命名构造函数。它不表示类型。因此,根据[temp.res]的上述引用,该程序格式错误(需要诊断)。
换句话说,这似乎是一个GCC错误(虽然Clang的错误信息也可以使用一些改进)。