Clang:错误:无效使用非静态数据成员 [英] Clang: error: invalid use of non-static data member
问题描述
这个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
pre>
#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
使用示例:
//在块级别:
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
ornullptr
may trigger compiler warnings for possible dereference of a null pointer (despite the fact thatsizeof
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)
andsizeof Expression
, as they are formally not the same, even ifsizeof(Expression)
works — as long assizeof (Expression)
is valid. So, the most correct and portable form would besizeof(decltype(Expression))
, but unfortunately it was made available only in C++11; some compliers have providedtypeof(Expression)
for a long time, but this never was a standard extension.这篇关于Clang:错误:无效使用非静态数据成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!