Clang:错误:无效使用非静态数据成员 [英] Clang: error: invalid use of non-static data member

查看:565
本文介绍了Clang:错误:无效使用非静态数据成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个GCC是太好了,做什么Dev认为它会做,或者ang叨对于某事过于lyly。我在标准中缺少一些微妙的规则,其中clang在抱怨这个

时是正确的

或者我应该使用代码的第二位,基本上是offsetof的工作原理

  [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:错误:无效使用非静态数据成员'name'
std :: cout<< sizeof(Foo :: name)<< std :: endl;
~~~~~ ^ ~~~
1错误生成。
[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


解决方案


我发现添加 -std = c ++ 11 停止它抱怨。


现代GCC版本允许在 std = c ++ 98 模式。但是,旧版本,如我的GCC 3.3.6, 抱怨并拒绝编译。


现在我不知道C ++ 98的哪个部分违反了这段代码。


维基百科明确指出, C ++ 11,并参考 N2253 < a>,这说明语法最初不被C ++ 98标准视为无效,但随后有意地澄清为不允许这一点(我不知道非静态成员字段与其他变量在数据方面有什么不同)类型)。一段时间后,他们决定使这个语法有效,但是直到C ++ 11。



同一个文档提到了一个丑陋的解决方法,这也可以在整个web:

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

看起来就像使用 0 NULL nullptr 可能会触发编译器警告可能取消引用空指针(尽管事实上 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
//使用`nullptr`可能会触发警告。
#define CxxSizeOf(TYPE,FIELD)(sizeof(reinterpret_cast< const TYPE *>(1234) - > FIELD))
#endif
pre>

使用示例:

  //在块级别:

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



//函数内部:

void Foo(void){

size_t nSize = CxxSizeOf(SomeHeader,Flags);

} // end function Foo(void)

顺便说一句,注意 sizeof(Type) sizeof Expression 的语法差异,因为它们在形式上不一样, code> sizeof(Expression)工程 - 只要 sizeof(Expression)有效。因此,最正确和可移植的形式是 sizeof(decltype(Expression)),但不幸的是它只能在C ++ 11中使用;一些遵从者提供 typeof(Expression)很长时间,但这从来不是标准扩展。


Is this gcc being overly nice and doing what the dev thinks it will do or is clang being overly fussy about something. Am I missing some subtle rule in the standard where clang is actually correct in complaining about this

Or should I use the second bit of code which is basically the how offsetof works

[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

解决方案

I found adding -std=c++11 stops it complaining. GCC is fine with it in either version.

Modern GCC versions allow this even in -std=c++98 mode. However, older versions, like GCC 3.3.6 of mine, do complain and refuse to compile.

So now I wonder which part of C++98 I am violating with this code.

Wikipedia explicitly states that such a feature was added in C++11, and refers to N2253, which says that the syntax was not considered invalid by the C++98 standard initially, but then intentionally clarified to disallow this (I have no idea how non-static member fields are any different from other variables with regard to their data type). Some time later they decided to make this syntax valid, but not until C++11.

The very same document mentions an ugly workaround, which can also be seen throughout the web:

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

It looks like simply using 0, NULL or nullptr may trigger compiler warnings for possible dereference of a null pointer (despite the fact that sizeof never evaluates its argument), so an arbitrary non-zero value might be used instead, although it will look like a counter-intuitive "magic constant". Therefore, in my C++ graceful degradation layer I use:

#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

Usage examples:

// 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)

By the way, note the syntax difference for sizeof(Type) and sizeof Expression, as they are formally not the same, even if sizeof(Expression) works — as long as sizeof (Expression) is valid. So, the most correct and portable form would be sizeof(decltype(Expression)), but unfortunately it was made available only in C++11; some compliers have provided typeof(Expression) for a long time, but this never was a standard extension.

这篇关于Clang:错误:无效使用非静态数据成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆