当前位置: 首页 > 知识库问答 >
问题:

错误 C2327:不是类型名称、静态或枚举器

闻人杰
2023-03-14

我在windows上遇到“错误C2327”。< br >我减少了代码,测试程序出现了类似的错误

#include <boost/intrusive/list.hpp>
#include <iostream>

class Test {
protected:
         typedef Test self_type;
         boost::intrusive::list_member_hook<> order_hook;
public:
         typedef boost::intrusive::member_hook<self_type,
                            boost::intrusive::list_member_hook<>,
                            & Test::order_hook > order_hook_type;
};

这在g上工作正常,但在Windows上它给出以下错误:

test.cpp(11) : error C2327: 'Test::order_hook' : is not a type name, static, or enumerator
test.cpp(11) : error C2065: 'order_hook' : undeclared identifier

请帮忙。我缺少什么窗户?

共有3个答案

宇文和同
2023-03-14

请改用function_hook。基本上,这允许您在静态函数的主体中获取成员变量的地址,该函数可以在类 Test 主体之外定义。

#include <boost/intrusive/list.hpp>
#include <boost/intrusive/parent_from_member.hpp>

class Test {
protected:
     boost::intrusive::list_member_hook<> order_hook;
private:
     struct hook_access
     {
         typedef boost::intrusive::list_member_hook<> hook_type;
         typedef hook_type* hook_ptr;
         typedef hook_type const* const_hook_ptr;
         typedef Test value_type;
         typedef value_type* pointer;
         typedef value_type const* const_pointer;

         static hook_ptr to_hook_ptr( value_type& i_value )
         { return & i_value.order_hook; }
         static const_hook_ptr to_hook_ptr( value_type const& i_value )
         { return & i_value.order_hook; }
         static pointer to_value_ptr( hook_ptr i_hook );
         static const_pointer to_value_ptr( const_hook_ptr i_hook );
     };
     friend struct hook_access; 
public:
     typedef boost::intrusive::function_hook< Test::hook_access > order_hook_type;
};

Test::hook_access::pointer 
Test::hook_access::to_value_ptr
( Test::hook_access::hook_ptr i_hook )
{ return boost::intrusive::get_parent_from_member< Test >( i_hook, & Test::order_hook ); }

Test::hook_access::const_pointer 
Test::hook_access::to_value_ptr
( Test::hook_access::const_hook_ptr i_hook )
{ return boost::intrusive::get_parent_from_member< Test >( i_hook, & Test::order_hook ); }
司徒炎彬
2023-03-14

TL;dr: Visual Studio有个bug:你的代码是合法的。

< code>[C 11: 14.3.2/1]:非类型、非模板模板参数的模板参数应为以下之一:

  • 对于整型或枚举类型的非类型模板参数,模板参数类型的转换常量表达式 (5.19);或
  • 非类型模板参数的名称;或
  • 一个常量表达式 (5.19),它指定具有静态存储持续时间和外部或内部链接的对象地址,或具有外部或内部链接的函数,包括函数模板和函数模板 ID,但不包括非静态类成员,表示(忽略括号)为

[C 11:5.3.1/3]:一元的结果

[C11:3.4.3.1/1]:如果限定id的嵌套名称说明符指定了一个类,则在该类的范围(10.2)中查找嵌套名称说明符之后指定的名称,但下列情况除外。名称应代表该类或其一个基类的一个或多个成员(第10条)。[注:类成员可以在其潜在作用域(3.3.7)的任何点使用限定id引用。-结束注释]上述名称查找规则的例外情况如下:

    < li >按照3.4.3中的规定查找析构函数名; < li >在类成员访问中,以与conversion-type-id相同的方式查找conversion-function-id的conversion-type-id(参见3 . 4 . 5); < li >在出现整个后缀表达式的上下文中查找template-id的template-argument中的名称。 < li >查找using-declaration (7.3.3)中指定的名称时,还会找到隐藏在同一作用域(3.3.10)中的类名或枚举名。

这里没有例外,所以我们看一下类成员的“潜在作用域”:

< code>[C 11: 3.3.7/1]:以下规则描述了类中声明的名称的范围。

  1. 类中声明的名称的潜在范围不仅包括名称声明点之后的声明性区域,还包括所有函数体、非静态数据成员的大括号或相等的初始化器以及该类中的默认参数(包括嵌套类中的此类内容)
  2. […]

GCC正确编译并执行以下测试用例:

template <typename B, int B::* PTM>
struct A {};

struct B
{
    int x;

    typedef A<B, &B::x> a;
};

int main() {
    B b;
}

而Visual Studio 2012 Express错误地输出:

常枫涟
2023-03-14

dr:Visual Studio是对的——你不能把typedef放在那里。
Boost 文档对此表示正确,但没有解释原因。

< code>[C 11: 14.3.2/1]:非类型、非模板模板参数的模板参数应为以下之一:

  • 对于整型或枚举类型的非类型模板参数,模板参数类型的转换常量表达式 (5.19);或
  • 非类型模板参数的名称;或
  • 一个常量表达式 (5.19),它指定具有静态存储持续时间和外部或内部链接的对象地址,或具有外部或内部链接的函数,包括函数模板和函数模板 ID,但不包括非静态类成员,表示(忽略括号)为

[C 11:5.3.1/3]:一元的结果

[C11:8.3.3/2][/code>给出了一个示例,只要指向成员的指针没有实际初始化,不完整类型的成员指针就有效,尽管没有明确声明,但这意味着要实际获取某个C::m的地址,C必须是完整类型。事实上,直到<code>C</code>是一个完整的类型,<code>C::m</code<才真正存在。

有一些类似的规则更清晰:

[C 11:9.2/10]:非静态(9.4)数据成员不得具有不完整的类型。特别是,类C不得包含类C的非静态成员,但它可以包含指向类C对象的指针或引用。

类型定义点,Test 不是一个完整的类型:

< code>[C 11: 9.2/2]:在类说明符的结束< code>}处,类被视为完全定义的对象类型(3.9)(或完整类型)。在类成员规范中,该类在函数体、默认参数、异常规范和非静态数据成员的大括号或相等初始值设定项(包括嵌套类中的此类内容)中被认为是完整的。否则,在它自己的类成员规范中,它被认为是不完整的。

因此,不能在该位置使用指向成员的指针。您必须编写<code>typedef</code>,使其出现在类定义的关闭<code>}</code>之后,或使指向的对象成为非成员,或<code>静态</code>成员。

GCC 在这方面必须有一个错误或扩展,因为以下测试用例可以成功编译和执行:

template <typename B, int B::* PTM>
struct A {};
 
struct B
{
    int x;
 
    typedef A<B, &B::x> a;
};
 
int main() {
    B b;
}

而Visual Studio 2012 Express正确输出:

 类似资料:
  • 问题内容: Java中的静态和非静态枚举有什么区别?两种用法是相同的。 正确吗 所有静态的都在启动时加载到内存中,非静态的则按需加载 ? 如果是,那么哪种方法更好?将某些数据始终保留在内存中还是每次使用服务器资源加载它们? 问题答案: 所有的都是有效的。如果您有嵌套的枚举,则它与相同。 所有类都是延迟加载的(枚举或其他),但是在加载时,它们会一次全部加载。也就是说,您不能加载一些常量,而不能加载其

  • 问题内容: 我似乎无法像从内部类内部那样从枚举内部访问周围类的实例成员。这是否意味着枚举是静态的?是否可以访问周围类的实例的范围,还是必须在需要的地方将实例传递给枚举的方法? 问题答案: 是的,嵌套枚举是隐式静态的。 嵌套枚举类型是隐式静态的。可以将嵌套枚举类型显式声明为静态。a

  • 这个类包含一个静态方法getInstance(我想模拟它),以提供一个singleton对象和几个声明为公共静态的枚举类(在异常中可以看到其中一个名为ReadSets的类)。下面是这个类的样子。 有没有关于如何修复的线索?

  • 我有以下代码: 这段代码编译得很好,但如果我将定义移到类之外,它就不会: gcc错误消息: 叮当的错误消息: MSVC 2019错误消息: 如果它在测试中将更改为,或者如果我将重命名为其他名称,它也可以很好地编译。 你能解释一下为什么第一个版本编译而第二个版本没有编译吗?你能告诉我这个错误的标准措辞吗? 编辑:我发布了来自不同编译器的错误消息。当@cigien pointed clang trun

  • 大家好! 我的教授还希望我使用下面代码中包含的枚举,我甚至不知道从哪里开始。 任何帮助都会很棒。

  • 我应该工作,对吧?但它不是!!!!它告诉我dbValue可以转换为RelationActiveEnum...

  • 问题内容: 这来自有效的Java: 请注意,操作常量是从创建常量之后运行的静态块放入stringToEnum映射中的。试图使每个常量从其自己的构造函数中放入映射中将导致编译错误。这是一件好事,因为如果合法,它将导致NullPointerException。除编译时常量字段外,不允许枚举构造函数访问枚举的静态字段。此限制是必需的,因为在构造函数运行时尚未初始化这些静态字段。 我的问题是关于这条线的:

  • 问题内容: 编译错误: 解决办法? 问题答案: Java不允许您在函数局部内部类内定义非最终静态字段。只允许顶级类和静态嵌套类具有非最终静态字段。 如果您要在班级中添加一个字段,请将其放在班级级别,如下所示: