有谁知道为什么using声明似乎不适用于从依赖基类导入类型名称?它们适用于成员变量和函数,但至少在GCC 4.3中,它们似乎被忽略了类型。
template <class T>
struct Base
{
typedef T value_type;
};
template <class T>
struct Derived : Base<T>
{
// Version 1: error on conforming compilers
value_type get();
// Version 2: OK, but unwieldy for repeated references
typename Base<T>::value_type get();
// Version 3: OK, but unwieldy for many types or deep inheritance
typedef typename Base<T>::value_type value_type;
value_type get();
// Version 4: why doesn't this work?
using typename Base<T>::value_type;
value_type get(); // GCC: `value_type' is not a type
};
我有一个带有一组allocator-style typedef的基类,我希望在几个继承级别中继承它们。到目前为止,我发现的最佳解决方案是上面的版本3,但我很好奇为什么版本4似乎不起作用。 GCC接受使用声明,但似乎忽略它。
我检查了C ++标准,C ++程序。郎。第3版。 [Stroustrup]和C ++模板[Vandevoorde,Josuttis],但似乎都没有解决使用声明是否可以应用于依赖基类类型。
如果在GCC邮件列表中查看另一个示例here is the same question being asked,但没有真正回答,则有帮助。提问者表示他已在其他地方看到“使用typename”,但GCC似乎并不支持它。我没有其他符合标准的编译器可用于测试它。
答案 0 :(得分:10)
正如Richard Corden所指出的那样,2003年标准批准后C++ Standard Core Language Defect Reports解决了这个问题:How do the keywords typename/template interact with using-declarations?
建议的决议(2003年4月, 2003年10月修订):
在底部添加一个新段落 7.3.3 [namespace.udecl]:
如果使用声明使用 关键字typename并指定一个 依赖名称(14.7.2 [temp.dep]), 这个名字由 using-declaration被视为a typedef-name(7.1.3 [dcl.typedef])。
此文本似乎没有出现在2003年10月15日的第二版标准中。
GCC尚未实施此决议,如bug 14258中所述:
-------评论#3来自Giovanni Bajo 2004-02-27 12:47 [回复] ------- 问题是我们的USING_DECL没有 记录“typename”,即 事实上,它是一种类型 通过它进口。这曾经工作过 感谢隐式类型名称 延伸,我相信。
重复bug 21484表示'使用typename'适用于Comeau和Intel编译器。由于MSVC将所有名称视为依赖,因此该编译器不需要(但允许)该构造。
答案 1 :(得分:-2)
在为Base :: value_type声明typedef之前,您没有在Base的模板中包含访问说明符(public / protected / private)。因此,它默认为private,并且在从Base派生的类中无法访问。