Clang:错误:无效使用非静态数据成员

时间:2015-03-31 02:36:53

标签: c++ g++ clang++

这个gcc是不是太好了,做了开发人员认为它会做的事情,或者是对某些事情过于挑剔的铿锵声。我是否在标准中遗漏了一些微妙的规则,其中clang实际上正在抱怨这个

或者我应该使用第二位代码,这基本上就是偏移量的工作原理

[adrian@localhost ~]$ g++ -Wall -pedantic -ansi a.cc
[adrian@localhost ~]$ a.out
50
[adrian@localhost ~]$ cat a.cc
#include <iostream>

struct Foo
{
   char name[50];
};

int main(int argc, char *argv[])
{
   std::cout << sizeof(Foo::name) << std::endl;
   return 0;
}


[adrian@localhost ~]$ clang++ a.cc
a.cc:10:29: error: invalid use of non-static data member 'name'
   std::cout << sizeof(Foo::name) << std::endl;
                       ~~~~~^~~~
1 error generated.
[adrian@localhost ~]$ g++ -Wall -pedantic -ansi b.cc
[adrian@localhost ~]$ a.out
50
[adrian@localhost ~]$ cat b.cc
#include <iostream>

struct Foo
{
   char name[50];
};

int main(int argc, char *argv[])
{
   std::cout << sizeof(static_cast<Foo*>(0)->name) << std::endl;
   return 0;
}


[adrian@localhost ~]$ clang++ b.cc
[adrian@localhost ~]$ a.out
50

1 个答案:

答案 0 :(得分:1)

  

我发现添加-std=c++11会阻止它抱怨。 GCC很好   在任一版本中使用它。

现代GCC版本即使在-std=c++98模式下也允许这样做。但是,旧的版本,如我的GCC 3.3.6,抱怨并拒绝编译。

  

所以现在我想知道C ++ 98的哪一部分违反了这段代码。

维基百科明确指出这样的功能是在C ++ 11中添加的,并且引用了N2253,它表示C ++ 98标准最初认为语法无效,但后来有意澄清为不允许这样做(我不知道非静态成员字段与其数据类型的其他变量有何不同)。一段时间后,他们决定使这种语法有效,但直到C ++ 11。

同一份文件提到了一个丑陋的解决方法,也可以在整个网络上看到:

sizeof(((Class*) 0)->Field)

看起来简单地使用0NULLnullptr可能会触发编译器警告,以便可能取消引用空指针(尽管sizeof永远不会评估其参数),因此可能会使用任意的非零值,尽管它看起来像一个反直觉的“魔法常数”。因此,在我的C ++优雅降级层中,我使用:

#if __cplusplus >= 201103L
    #define CXX_MODERN 2011
#else
    #define CXX_LEGACY 1998
#endif


#ifdef CXX_MODERN
    #define CXX_FEATURE_SIZEOF_NONSTATIC
    #define CxxSizeOf(TYPE, FIELD) (sizeof TYPE::FIELD)
#else
    // Use of `nullptr` may trigger warnings.
    #define CxxSizeOf(TYPE, FIELD) (sizeof (reinterpret_cast<const TYPE*>(1234)->FIELD))
#endif

用法示例:

// On block level:

class SomeHeader {
public:

    uint16_t Flags;

    static CxxConstExpr size_t FixedSize =
#ifdef CXX_FEATURE_SIZEOF_NONSTATIC
        (sizeof Flags)
#else
        sizeof(uint16_t)
#endif
    ;


}; // end class SomeHeader



// Inside a function:

void Foo(void) {

    size_t nSize = CxxSizeOf(SomeHeader, Flags);

} // end function Foo(void)

顺便说一句,请注意sizeof(Type)sizeof Expression的语法差异,因为它们在形式上并不相同,即使sizeof(Expression)有效 - 只要sizeof (Expression)sizeof(decltype(Expression))有效。因此,最正确和可移植的形式是typeof(Expression),但遗憾的是它仅在C ++ 11中可用;一些编制者长期提供data.table,但这绝不是标准的扩展。