【问题标题】:Why can't this public member function call decltype on a private struct member declared inside the class?为什么这个公共成员函数不能在类中声明的私有结构成员上调用 decltype?
【发布时间】:2025-11-29 03:40:01
【问题描述】:

以下代码(粗略地表示我正在处理的一些序列化内容)使用 g++ (http://ideone.com/0rsGmt) 进行编译,但 Visual Studio Express 2013 RC 失败并出现以下错误:

Error 1 error C2326: 'void foo::print(void)' : function cannot access 'foo::bar::member_'
Error 2 error C2039: 'bar' : is not a member of 'foo'

代码:

#include <iostream>

class foo
{   
    private:
        struct bar
        {
            int member_;
        };

    public:
        void print()
        {
            std::cout << sizeof(decltype(foo::bar::member_)) << std::endl;
        }
};

int main(int argc, char* argv[])
{
    foo f;
    f.print();
    return 0;
}

怎么了? Visual Studio 不足还是其他?显然我可以将结构声明移出类; Daniel Frey 在下面提供了一种解决方法;但我想知道为什么上面的代码无法在 Visual Studio 中按原样编译。

更新: 接受的答案说它应该可以工作,但对于 Microsoft 来说,通常情况下它不会。我在这里填写了一个错误报告:http://connect.microsoft.com/VisualStudio/feedback/details/801829/incomplete-decltype-support-in-c-11-compiler

(如果有人可以为问题提出更好的标题,我将不胜感激!)

【问题讨论】:

  • 尝试将bar移动到print之上,即改变顺序。
  • @DanielFrey,我交换了它们,但在 Visual Studio Express 2013 RC 中仍然遇到相同的错误。
  • 对于它的价值(这可能并不多),这在 clang 3.2 上编译得很好。 decltype(bar::member_) 也是如此(即没有 foo)。
  • Downvoter:请建议如何改进问题!

标签: c++ visual-studio c++11 decltype visual-studio-2013


【解决方案1】:

我认为您的代码应该工作(如在 GCC 或 Clang 上),根据

5 个表达式 [expr]

8 在某些情况下,未计算的操作数会出现(5.2.8、5.3.3、5.3.7、7.1.6.2)。未计算的操作数不会被计算。未计算的操作数被视为完整表达式。 [注意: 在未计算的操作数中,可以命名非静态类成员(5.1),并且对象或函数的命名本身并不要求提供定义(3.2)。 — 尾注 ]

似乎 VC++ 没有实现注释所阐明的内容,因此您需要一个(伪造的)实例作为解决方法来让 VC++ 满意。这应该有效:

void print()
{
    std::cout << sizeof(std::declval<bar>().member_) << std::endl;
}

请注意,我删除了 decltype,因为 sizeof 可以直接处理表达式。

【讨论】:

  • 这样做有运行时成本吗? “真实”代码有许多结构成员,在许多地方都调用了 decltype。速度在这里并不重要,但看起来有点臭!尤其是因为 g++ 可以按预期处理。
  • @DrTwox 不,没有运行时开销。 std::declval 只声明但未定义,因此只能在未评估的上下文中使用,这意味着不执行任何代码。
【解决方案2】:

也许你的代码的问题是结构就像类,你在类中定义结构,但编译器不知道这个类(或结构)存在,直到它编译整个类。

【讨论】:

  • 我向您保证,struct bar 的位置是故意的,并且是 OP 首先提出这个问题的根本原因。他不仅仅是在问如何获得可以编译的东西。他在问为什么他没有编译关于decltype()的使用。
  • 我知道,我只是说了大概的原因。
最近更新 更多