“使用typename”指令是否未由编译器实现?

时间:2014-05-24 17:22:00

标签: c++ using nested-class typename

我有一些看起来像这样的代码:

namespace myLibrary
{
    class A
    {
    public:
        struct Nested
        {
            ...
        };

        ...
    };
}

在代码的其他部分,我需要访问A.因为我喜欢可读的代码,我也喜欢using指令:

using myLibrary::A;
...
A a;

现在,在某些时候我还需要访问我的嵌套类,所以我想写这样的东西:

using myLibrary::A::Nested;

显然,编译器不能知道这是一个嵌套类而不是类成员,并且给了我一个错误:

error : using declaration can not refer to class member

我无法理解为什么这不能解决问题:

using typename myLibrary::A::Nested;

编译器仍然给出了完全相同的错误!

幸运的是,我有其他选择:

// Using a typedef
typedef myLibrary::A::Nested Nested;

// Using the new C++11 syntax for type aliasing
using Nested = myLibrary::A::Nested;

但我想了解为什么使用typename 指令不起作用。它不符合我的想法吗?或者它不是由编译器实现的?如果是后者,是否有理由呢?

2 个答案:

答案 0 :(得分:4)

没有"使用typename指令"。有 using-directives using-declarations

您没有使用任何 using-directives ,并且它们在任何情况下都与问题无关(它们命名名称空间,并且不能使用类型名称关键字)。

using-declarations 恰好出现在类模板中,并且恰好出现名称依赖类型时,他们必须使用typename关键字,就像恰好在模板中的其他任何内容一样并恰巧命名一个依赖类型。

例如:

template <typename A, typename R>
class Functor : public std::unary_function<A, R>
{
    using typename std::unary_function<A, R>::result_type;
    using typename std::unary_function<A, R>::argument_type;
 public:
    result_type operator() (argument_type) {}
};

在您的情况下,名称空间声明似乎不是类模板主体的一部分,实际上它似乎在命名空间范围内,在这种情况下尝试命名类成员(不是无论是类型,功能还是其他任何内容都违反了7.3.3[namespace.udecl]/8

  

类成员的 using-declaration 应为成员声明

由于编译器正确诊断出&#34;错误:使用声明无法引用类成员&#34;

答案 1 :(得分:3)

引用命名空间成员using的{​​{1}}声明只能出现在命名空间或本地范围内。

引用类成员A的{​​{1}}声明只能出现在从using派生的类中的类作用域(以及成员声明)中。实际上,这种Nested声明在语法上被认为是成员声明。它们用于调整访问限定,并且(使用Nested)允许使用类型相关的基础成员而无需限定。这些是特定用例,因此成员using声明有点专门。

嵌套类其封闭类的成员。通常应避免使用类外壳作为名称空间的替代。元编程为规则提供了一些例外,但在这些情况下,您仍然不会使用typename声明,至少在命名空间范围内,因为命名空间不能模板化。继承一个空的元编程课是可行的,但请注意意大利面。

using指令是另一种野兽。它看起来像using,它将一个名称空间链接到另一个名称空间作为名称查找中的回退路径。