访问与内部类型具有相同名称的静态成员 [英] Accessing a static member that has the same name as an inner type

查看:104
本文介绍了访问与内部类型具有相同名称的静态成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有几个类定义序列,其值必须在编译时通过 value 成员可用,在运行时作为类型的实际实例。所以我的基本类型的算术序列看起来有点像这样,

I have a few classes that define sequences whose values must be available both at compile-time through a value member and at runtime as an actual instance of the type. So my base types for an arithmetic sequence looks a little like this,

template<int A, int D>
struct ArithmeticSequence : public Sequence {
    ArithmeticSequence(VALUE v)
        : Sequence(v) {}

    template<unsigned int N>
    struct VALUE_N : public VALUE {
        static const int value = A+(D*N);
        operator int() { return value; }
    };
};

class Sequence 目前只定义一个内部类 VALUE (目前为空)和构造函数需要 VALUE ,但我将移动 VALUE 中的运算符int() / code>将定义迭代器等等。

class Sequence currently just defines an inner class VALUE (currently empty) and a constructor that takes a VALUE, but I will move the operator int() of VALUE_N into VALUE and Sequence will define iterators, etc, further down the line.

现在,类应该从 ArithmeticSequence 并为序列的每个成员定义常量。我有两个方法,我认为这将工作,如果我不介意序列能够从相关序列的成员构建的实例(即,具有相同的初始值和共同差异的序列),我可以使用 typedef

Now, classes should extend from ArithmeticSequence and define constants for each of the members of the sequence. I've got two methods that I think will work for this, if I don't mind instances of sequences being able to be constructed from members of related sequences (that is, sequences with the same initial value and common difference), I can use typedef:

struct mySequence : public ArithmeticSequence<0,1> {
    mySequence(VALUE val = VALUE_N<0>::value)
        : ArithmeticSequence(val) {}

    typedef VALUE_N<0> zeroth;
    typedef VALUE_N<1> first;
    // ...
};

如果我这样做,我可以从 VALUE_N

And if I do, I can extend from VALUE_N:

struct mySequence : public ArithmeticSequence<0,1> {
    mySequence(VALUE val = VALUE_N<0>::value)
        : ArithmeticSequence(val) {}

    struct zeroth : public VALUE_N<0> {};
    struct first  : public VALUE_N<1> {};
    // ...
};

在这两种情况下,我想我可以使用 mySequence :: zeroth :: value 以获取编译时的值,并使用 mySequence :: zeroth()来获取运行时对象。但是使用第二种方法会导致编译器混淆我是否声明一个函数或初始化一个实例,所以我需要 mySequence s1((mySequence :: zeroth())); 而不是 mySequence s1(mySequence :: zeroth())

In both these cases I think I can use mySequence::zeroth::value to get at the value at compile time, and mySequence::zeroth() to get a runtime object. However using the second method causes the compiler confusion as to whether I'm declaring a function or initializing an instance, so I need, mySequence s1 ((mySequence::zeroth())); instead of mySequence s1 (mySequence::zeroth()).

下面是有效的:

struct mySequence : public ArithmeticSequence<0,1> {
    mySequence(VALUE val = VALUE_N<0>::value)
        : ArithmeticSequence(val) {}

    struct zeroth : public VALUE_N<0> {};
    static const zeroth zeroth;
    struct first  : public VALUE_N<1> {};
    static const first first;
    // ...
};

但我的问题(最后)是什么是关于我访问哪个任何时候?我可以使用 static const int i = mySequence :: zeroth :: value mySequence s1(mySequence :: zeroth),所以正确的事情似乎发生在那里,但如果我说 mySequence :: zeroth z 而不是处理 zeroth 作为类,它将其视为变量。这不是一个问题,在这种情况下,因为我不想让人们创建新的 mySequence :: zeroth '或任何其他值,但我想如果我不了解什么时候会使用每一个我可能会让自己陷入麻烦,在以后的日期。

But my question (finally) is, what are the rules as to which one I'm accessing at any time? I can use static const int i = mySequence::zeroth::value and, mySequence s1 (mySequence::zeroth), so the right thing seems to happen there, but if I say mySequence::zeroth z instead of treating zeroth as a class it treats it as the variable. This isn't a problem in this case since I don't want people creating new mySequence::zeroth's or any other value, but I think if I don't understand when it will use each one I may let myself in for trouble at a later date.

对不起,超长篇文章,谢谢你的时间和耐心对于任何人谁得到了这么远。我现在想知道,如果我应该把所有的后面的故事,或只是简单地问问题,如果共识是我应该有,我将编辑它。感谢。

Sorry about the extra long post, and thankyou in advance for your time and patience for anyone who got this far. I'm wondering now if I should have put in all the back story or just simply asked the question, if the concensus is I should have, I'll edit it down. Thanks.

编辑。请注意,如我上面写的,使用struct方法,而不是typedef不提供任何保护,使用另一个相关序列成员构造一个序列对象,它是需要的,I

Edit. Please note, as I have written it above, using the struct method as opposed to the typedef does not provide any protection against using another "related" sequences members to construct a sequence object, it is needed, I think, however for the last example to work.

推荐答案

枚举器,函数和对象的名称隐藏了枚举和类的名称它们在同一范围内声明。在你的case,数据成员名隐藏结构的名称。您可以通过特殊查找访问隐藏的类型名称:

The names of enumerators, function and objects hide the names of enumerations and classes that are declared in the same scope. In your case, the data member name hides the name of the struct. You can access the hidden type name by special lookups:


  • ::
  • 用于指定基类的名称忽略任何非类型的名称。

  • 在详细说明的类型说明符中指定的名称会忽略对象,函数和枚举器名称。

因此,以下详细说明的类型说明符有效,并且指类

Thus, the following elaborated type specifier is valid and refers to the class

struct mySequence::zeroth var;

此外,注意,在类范围中,成员声明更改了该声明中使用的名称。在你的情况下,让我们先 static const first; 。第一个名称将引用类型,但在 mySequence 的完整范围中,该名称将引用数据成员。该标准表示

Also, note that it is ill-formed when in class scope a member declaration changes the meaning of a name used in that declaration. In your case, let's take static const first first;. The first name will refer to the type, but in the complete scope of mySequence, that name would refer to the data member. The Standard says


在类S中使用的名称N在其上下文中引用相同的声明,并且在完成

A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No diagnostic is required for a violation of this rule.

您的编译器不需要诊断它,这是一个短语意味着它是有效未定义的行为(良好的编译器警告你用类似成员变化的名称的意义)。虽然我怀疑上面的规则是打算应用在这种情况下(因为它的措词,它当然适用虽然),你可以清除代码使用详细的类型说明符

Your compiler is not required to diagnose it, which is a phrase meaning that it is effectively undefined behavior (good compilers warn you with something like "member changes meaning of name"). Albeit i doubt that the above rule is intended to apply in this case (as it is worded, it certainly applies though), you can clear the code up by using an elaborated type specifier

struct first  : public VALUE_N<1> { };
static const struct first first;

请注意,您需要使用详细说明的类型说明符静态成员。一些编译器允许你使用注入的类名来引用类型(GCC在过去)

Notice that you are required to use the elaborated type specifier in the out-of-class definition of the static member. Some compilers allow you to use the injected class name for refering to the type too (GCC did, in the past)

const struct mySequence::first mySequence::first;

以下使用注入的类名。 首先出现在 :: 之前,并忽略数据成员。但是编译器必须查找名称 mySequence :: first :: first 的第一个的构造函数,而不是它的类类型

The following uses the injected class name. first appears before :: and ignores the data member. But the compiler has to lookup the name mySequence::first::first to first's constructor and not to its class type

const mySequence::first::first mySequence::first;

这篇关于访问与内部类型具有相同名称的静态成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆