【问题标题】:Are "using typename" directives not implemented by compilers?编译器是否没有实现“使用类型名”指令?
【发布时间】:2014-05-24 17:22:00
【问题描述】:

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

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;

但我想了解为什么 using typename 指令不起作用。它不做我认为它做的事吗?或者它不是由编译器实现的?如果是后者,那有什么原因吗?

【问题讨论】:

  • 据我所知,它只适用于命名空间成员,而不是类成员:en.cppreference.com/w/cpp/keyword/using
  • @DiscoStu:也许,但在这种情况下,为什么要引入“typename”关键字?它似乎应该使用:en.cppreference.com/w/cpp/language/using_declaration
  • 您尝试使用 using 声明的上下文是什么?
  • Nested 必须始终称为A::Nested,除非它位于A 的成员变量或函数中。如果您的代码似乎要求在没有 A:: 的情况下谈论 Nested,这表明不将其作为嵌套类可能是更好的设计。
  • @MattMcNabb:如果你想知道,A 是描述机器人关节的类,而 Nested 是关节角度限制的结构。嵌套它对我来说很有意义,即使有时我必须从外部访问它。

标签: c++ using nested-class typename


【解决方案1】:

没有“使用类型名指令”。有using-directivesusing-declarations

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

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应该是一个member-declaration

编译器正确诊断为“错误:使用声明不能引用类成员”

【讨论】:

  • 非常感谢!很抱歉称其为“指令”。我认为区别在于“使用声明”是类主体中的那些,而“使用指令”是其他的。
【解决方案2】:

引用命名空间成员 Ausing 声明只能出现在命名空间或本地范围内。

引用类成员Nestedusing 声明只能出现在从Nested 派生的类中(连同成员声明)。事实上,这样的using 声明在语法上被认为是成员声明。它们用于调整访问资格,并且(使用typename)允许在没有资格的情况下使用依赖于类型的基的成员。这些是特定的用例,所以成员 using 声明有点特殊。

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

using 指令是一个不同的野兽。它看起来像using namespace,它将一个命名空间链接到另一个命名空间,作为名称查找中的后备路径。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-15
    • 1970-01-01
    • 2011-01-15
    • 2012-12-14
    • 2018-11-20
    相关资源
    最近更新 更多