Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inconsistent behavior of MSVC vs. GCC with sizeof

Consider the following code:

#include <cstddef>

class A
{
public:
    struct B
    {
        int M;
    };

    static void StaticFunc();
};

void A::StaticFunc()
{
    const std::size_t s0 = sizeof(::A::B::M);
    const std::size_t s1 = sizeof(A::B::M);
    const std::size_t s2 = sizeof(B::M);
}

int main()
{
    const std::size_t s3 = sizeof(A::B::M);
    return 0;
}

GCC compiles it, just warning about the unused variables.

Visual C++ 2015 however fails to compile it with:

error C2326: 'void A::StaticFunc(void)': function cannot access 'A::B::M'

on the lines

const std::size_t s0 = sizeof(::A::B::M);
const std::size_t s1 = sizeof(A::B::M);

in StaticFunc().

The other line s2 = ..., and s3 = ... in main() compile fine.

Is this a bug in MSVC, or do I miss something basic here?

like image 987
alain Avatar asked Oct 03 '16 13:10

alain


1 Answers

It is a bug in MSVC.

C++11/14 allows a non-static class member to be used in a non-evaluated context, see 5.1.1 [expr.prim.general] p. 13:

An id-expression that denotes a non-static data member or non-static member function of a class can only be used:

...

(13.3) — if that id-expression denotes a non-static data member and it appears in an unevaluated operand.

[ Example:

    struct S {
       int m;
    };
    int i = sizeof(S::m);        // OK
    int j = sizeof(S::m + 42);   // OK

— end example]

Edit: it looks like MSVC accepts B::M and doesn't accept A::B::M, which is a completely inexplicable behaviour. I don't see how it could be anything but a bug.

clang++ like g++ in C++11 and C++14 mode accepts the program. clang++ in C++03 mode rejects all 4 references to M (C++03 doesn't have anything like p. 13.3), whereas g++ in C++03 mode still accepts them (this is probably a g++ C++03 mode bug).

like image 150
n. 1.8e9-where's-my-share m. Avatar answered Sep 29 '22 06:09

n. 1.8e9-where's-my-share m.