简体   繁体   English

为什么 C 结构破解不适用于 C++ 模板声明?

[英]Why does the C struct hack not work for C++ template declarations?

C has this fun hack where one name can be used to declare both a type and a function: C 有这个有趣的技巧,其中一个名称可用于声明类型和 function:

struct foo {};
void foo(void);

Now, any time I write foo , the compiler assumes I mean the function unless I prefix it with struct :现在,每当我写foo时,编译器都会假定我的意思是 function ,除非我在它前面加上struct

foo();  // call void foo(void)
struct foo bar;  // declare variable of type struct foo

This works great in C++ even with namespaces and nesting: But it doesn't work with templates:即使使用命名空间和嵌套,这在 C++ 中也很有效:但它不适用于模板:

template <typename> void bar(void);
template <typename> struct bar {};
// error: conflicting declaration of template struct bar
// previous declaration: template void bar()

Why?为什么?

We already get to deal with disambiguators in dependent contexts:我们已经开始处理依赖上下文中的消歧器:

typename foo<A>::b();
foo<A>::template b<C>();

It doesn't seem much of a stretch to apply the regular rules to ambiguous template names of this kind.将常规规则应用于此类模棱两可的模板名称似乎并不难。

Suppose that having the same name is important to me.假设同名对我很重要。 Could I somehow make this work?我能以某种方式完成这项工作吗?

Why?为什么?

The answer is in the body of the question.答案在问题的正文中。 This works for classes and functions because in C there is a separate namespace for structure tags and function identifiers.这适用于类和函数,因为在 C 中,结构标签和 function 标识符有一个单独的命名空间。 If C++ aims to interoperate with C code, it must retain this behavior.如果 C++ 旨在与 C 代码互操作,则必须保留此行为。 One need only look at an API like the stat function taking a struct stat argument to realize why C++ retained the validity of such code.只需查看 API 之类的stat function struct stat可以了解为什么 C++ 保留了此类代码的有效性。 This working with namespaces is simply inline with C code residing in the global namespace (so ::stat and struct::stat should continue to work when needed).这种使用命名空间的方法只是与驻留在全局命名空间中的 C 代码内联(因此::statstruct::stat应该在需要时继续工作)。

However, in C++ the identifiers of class tags share a "namespace" with regular identifiers.但是,在 C++ 中,class 标签的标识符与常规标识符共享一个“命名空间”。 And so the validity of this "hack" is achieved with a special case in the C++ specification that simply hides classes when they would conflict.因此,这种“hack”的有效性是通过 C++ 规范中的一个特殊情况来实现的,该规范只是在类发生冲突时隐藏类。

[basic.scope.hiding] [基本.scope.hiding]

2 A class name or enumeration name can be hidden by the name of a variable, data member, function, or enumerator declared in the same scope. 2 class 名称或枚举名称可以通过变量名称、数据成员、function 或在同一 scope 中声明的枚举器的名称隐藏。 If a class or enumeration name and a variable, data member, function, or enumerator are declared in the same scope (in any order) with the same name, the class or enumeration name is hidden wherever the variable, data member, function, or enumerator name is visible. If a class or enumeration name and a variable, data member, function, or enumerator are declared in the same scope (in any order) with the same name, the class or enumeration name is hidden wherever the variable, data member, function, or枚举器名称可见。

It doesn't matter if the designers of C++ thought it was a good or bad idea. C++ 的设计者认为这是一个好主意还是坏主意并不重要。 There is legacy code that should continue to be accepted as valid by C++ compilers for ease of inter-operating with certain systems. C++ 编译器应继续接受遗留代码为有效,以便与某些系统进行互操作。

But there is no legacy code dealing with templates that requires the same behavior.但是没有处理需要相同行为的模板的遗留代码。 Templates are an entirely C++ construct (not related to C at all).模板完全是 C++ 构造(与 C 完全无关)。 And such, the language design doesn't have an outside constraint to add more special cases for template names too.因此,语言设计也没有外部约束来为模板名称添加更多特殊情况。 And so it doesn't.所以它没有。

Suppose that having the same name is important to me.假设同名对我很重要。 Could I somehow make this work?我能以某种方式完成这项工作吗?

No way to make it work comes to mind.没有办法让它工作。

The wording is in temp.pre-7 :措辞在temp.pre-7

A class template shall not have the same name as any other template, class, function, variable, enumeration, enumerator, namespace, or type in the same scope ([basic.scope]), except as specified in [temp.class.spec]... A class template shall not have the same name as any other template, class, function, variable, enumeration, enumerator, namespace, or type in the same scope ([basic.scope]), except as specified in [temp.class.spec ]...

None of the points in temp.class.spec conflict with this example. temp.class.spec中的所有点都与此示例不冲突。

So, as it stands, you can't have the same name for a class template and a function template.因此,就目前而言,class 模板和 function 模板不能使用相同的名称。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM