【问题标题】:Why is decltype not allowed on private member variables?为什么私有成员变量上不允许使用 decltype?
【发布时间】:2012-06-07 00:37:09
【问题描述】:

假设我有这样的课程:

class Foo
{
  std::vector<int> bar;

public:
  std::vector<int>& get_bar() { return bar; }
};

稍后,我想要另一个与bar 具有相同类型的变量。如果我能做到这一点,那对我来说很有意义:

decltype(Foo::bar) clone_of_bar;

但这不起作用。编译器告诉我 'std::vector Foo::bar' 是私有的

所以我最终不得不使用这样的东西:

std::remove_reference<decltype(std::declval<Foo>().get_bar())>::type clone_of_bar;

这可行,但看起来一团糟。也许有更简单的方法来做到这一点;我不太确定。但我真正想知道的是为什么我不能只使用decltype(Foo::bar)。为什么有人要关心bar 是私人的?我实际上并没有访问该变量。

decltype 是该语言的一个新特性。我只是不明白为什么它被设计成不能处理私有变量。

【问题讨论】:

  • 如果您能给我们一些 实际 示例,您将受益于在私人成员上使用 decltype,我将不胜感激。
  • 嗯,我有任何非常充分的理由想要这样做。这主要是出于好奇。但是我尝试使用它的情况是这样的:我使用的是 google protobuf,为此我定义了一些事件类型,然后 protobuf 为这些类型生成了一些代码。生成的代码看起来有点像我在问题示例中写的。问题是,我希望能够从 protobuf 消息中复制一些数据来做一些事情,如果我碰巧更改了 protobuf 消息中的类型,我不想更改代码。所以这就是我想做的。不过没什么大不了的。
  • 你不能只使用“auto x = somefoo.get_bar();” ?你会复制,但没有明确提供“x”的类型。
  • 我不能使用自动,因为副本是某个类的永久成员。基本上我有一个存储“状态”的类,这些 protobuf 消息包含状态的新点点滴滴。所以当一个protobuf消息进来时,我想摆脱旧状态的一部分并用新的替换它。 -- 所以无论如何,我不能使用auto,因为我必须在调用get_bar之前声明类型。
  • +1 我实际上有一个真实的例子,这是一个可验证的 PITA。 stackoverflow.com/q/14934749/975129 我必须使用decltype,因为可变参数函数将根据传入的参数返回不同的类型。作为一个邪恶的结果,我必须在我的at() 方法中公开我的m_map 成员? !?啊!我可能不得不使用你的解决方法,但是我必须添加一个不必要的 get 方法..

标签: c++ c++11 decltype


【解决方案1】:

在语言律师术语中,bar 是一个名称,要在 decltype 表达式中使用它,编译器必须进行正常的名称查找,这尊重访问控制。
为什么decltype 的设计与其他语言不同?你没有提出任何令人信服的论据来解释为什么它不应该与例如一致。 sizeof.

作为课程作者,我不希望您能够像这样查询私有实现细节。如果我希望该类型在类之外可用,我会定义一个公共 typedef,告诉您它是什么类型。

稍后,我想要另一个与bar具有相同类型的变量

您想要与私有实现细节具有相同类型的“另一个变量”吗?因此,如果Foo 类的作者重构了他们的代码并用其他一些实现细节替换了类型,那么你的代码突然改变了含义并且不相关的代码可能会突然停止编译或默默地有不同的行为,因为该代码愚蠢地依赖于私有细节不关它的事。这将在私有实现细节和Foo 的作者可能不知道存在的无关代码之间引入耦合!这是个糟糕的主意。

【讨论】:

  • 这似乎是个好主意。请问您是否有任何引用断言这是这种情况?
  • 断言什么? bar 是一个名称,必须通过名称查找找到?如果不进行名称查找,编译器如何知道Foo::bardecltype(Foo::bar) 中所指的内容?
  • +1,还建议使用auto clone= foo.get_bar()decltype(foo.get_bar()) clone 可能对用户有帮助?
  • @JonathanWakely 不,我的意思是一些文档说 decltype 出于这个原因在私人上不起作用?我没有学过 C++ > 10 年,只是听说过 decltype。
  • 感谢您的解释。但在你编辑说这是一个糟糕的想法之前,我更喜欢它,等等。我从来没有试图争辩说语言应该不同。我只是问为什么会这样。通常,我只是认为私有意味着外部函数不能以这种方式访问​​数据——但他们仍然可以知道数据存在,因为它就在头文件中。但我明白将 private 视为具有更严格含义的意义。
【解决方案2】:

decltype(Foo::bar) 确实Foo内部工作。

Foo 之外,你甚至不应该知道 Foo 有一个名为bar 的成员(这就是private 的意思),所以它当然不应该工作。

【讨论】:

    【解决方案3】:

    这是 4.8.0 版中修复的 gcc 错误:

    http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52816

    【讨论】:

    • 那个错误指的是与这个问题的内容略有不同的东西。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多