【问题标题】:Accessing type members in C++在 C++ 中访问类型成员
【发布时间】:2018-10-26 00:36:33
【问题描述】:

给定一个容器,例如 vector<int>

#include <vector>
using namespace std;
vector<int> v{1, 2, 3};

为什么访问iteratorconst_iterator 等公共类型成员似乎相当困难?据我了解,这些名称是类的一部分(不是对象),必须通过:: 访问以指定范围,但是当v 已知时,是否有理由禁止v.const_iterator? 示例:

int f(v.iterator it) {
    return *it;
}
// or
int g(v::iterator it) {
    return *it;
}

一种解决方法是使用decltype,如:

int h(decltype(v)::iterator it) {
    return *it;
}

但是这种方法甚至在类中也不起作用,因为以下失败:

class A
{
public:
    int h(decltype(x)::iterator it) {
        return *it;
    }
private:
    vector<int> x;
};

编辑

只是一点旁注。 正如所指出的,v.iterator 的含义将取决于使用点(编译时)忽略运行时多态性的v 的类型。但对于静态类成员也是如此。 示例:

struct A
{
    static const int x = 1;
};
struct B : public A
{
    static const int x = 2;
};
void eval()
{
    B b;
    A& ar = b;
    b.x; // 2
    ar.x; // 1, even though ar refers to the same underlying object (by the base type)
}

【问题讨论】:

  • 类型和对象存在是 C++ 中的平行宇宙(一个主要是编译时,其他主要是运行时。)点应用于对象,因此应该在运行时工作,因此不是对于类型。作为旁注,您可以在此处使用auto 来节省一些输入。
  • @FrançoisAndrieux 对不起,我的意思是最后一个例子
  • autoA::h 的函数参数中如何工作?对我来说,它不能用 c++17 编译。
  • decltype() 不是一种解决方法,而是一种解决方法,它适用于类,您只需要在使用之前定义该变量。
  • return *it + *(++it); UB 的好例子 :)

标签: c++


【解决方案1】:

正如@Slava 在 cmets 中指出的那样,decltype(x) 是这样做的方法:

#include <vector>
using namespace std;
vector<int> v{1, 2, 3};
int f(decltype(v)::iterator it) {
    return *it;
}

int g(decltype(v)::iterator it) {
    return *it;
}

class A
{
private:
    vector<int> x;
public:
    int h(decltype(x)::iterator it) {
        return *it;
    }
};

成员访问. 运算符和范围解析运算符:: 不得重载。正如您可能从名称中推断的那样,. 用于access members,而:: 用于访问scope

#include <iostream>

struct B {
    class iterator { };

    // no need for typename, compiler knows that we mean typedef B::iterator, as he can only find it
    iterator iterator1;

    // member named the same as class, ops!
    int iterator;

    // we need to use typename here, B::iterator is resolved as member
    // iterator iteartor3;
    typename B::iterator iterator2;
};

int main() {
    B bobj;

    // we access the member iterator inside b
    bobj.iterator = 1;

    // we declare object of B::iterator type
    // we need to tell compiler that we want only types
    typename B::iterator iterator;

    // this will work too
    typename decltype(bobj)::iterator iterator2;

    // we declare a member pointer to the iterator member inside some B class
    // no typename, as I want pointer to member, not pointer to... type
    int B::* pointer = &B::iterator;

    // this is just a pointer to the iterator specifically in bobj class
    int * pointer2 = &bobj.iterator;

    // foo(bar) 
    bobj.*pointer = 1;

    // this will work as expected
    int decltype(bobj)::* pointer3 = &B::iterator;
}

此外,C++ 中没有“类型成员”(至少我在 C++ 标准中找不到它们)。在类中声明为成员的类和枚举以及 typedef 声明称为“嵌套类型”或“嵌套类”。

【讨论】:

  • 类型成员成员。
  • 有趣的例子,但奇怪的是它没有在 clang 中编译:godbolt.org/z/HTZ3Bg
  • !并在 gcc 中工作。我觉得这个程序无效,但找不到原因。 Here is why.
【解决方案2】:

基本上,当您通过:: 访问它们时,C++ 允许您获取值或类型。所以MyType::AnotherTypeMyType::AValue 一样好。当您使用. 浏览一个实例时,它只意味着它想要解析一个符号,它是一种值(字段、函数等)。希望对您有所帮助。

【讨论】:

  • 问题不是关于什么 C++在做什么,而是为什么
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-27
相关资源
最近更新 更多