C++ 未找到在未命名命名空间中声明的函数的函数定义 - 如何解决?(Visual Studio 2015)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31900112/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Function definition not found for a function declared inside unnamed namespace - how to resolve? (Visual Studio 2015)
提问by sunny moon
I installed Visual Studio 2015and found that some of my code (that hadn't any problems in VS 2013) now has got some errors indicated by green squiggles (which are supposed to be a new productivity feature). Yet the code still compiles successfully.
我安装了 Visual Studio 2015并发现我的一些代码(在 VS 2013 中没有任何问题)现在出现了一些由绿色波浪线指示的错误(这应该是一个新的生产力功能)。但是代码仍然可以成功编译。
Here's a quick example:
这是一个快速示例:
namespace
{
void test1(); // what once was OK in VS 2013,
void test2(); // is now marked with squiggles in VS 2015
}
namespace named
{
void test3(); // OK, no problem
}
void test1() { /*...*/ }
void ::test2() { /*...*/ }
void named::test3() { /*...*/ }
int main() { /*...*/ }
Theese are the squiggles in question
这些是有问题的波浪线
Moving the mouse over them tells me that
将鼠标移到它们上面告诉我
Function definition for 'test1' not found
Function definition for 'test2' not found
未找到“test1”的函数定义
未找到“test2”的函数定义
Somehow it turns out that only functions declared inside unnamed namespace trigger the squiggles.
不知何故,只有在未命名命名空间内声明的函数才会触发波浪线。
How is it supposed to be resolved?
应该如何解决?
采纳答案by Sebastian Redl
The green squiggles don't tell you that there's an error, they tell you that there's an opportunity for the new refactoring tools to do something. (Red squiggles indicate an error.) In this case, they're informing you that there is no definition matching the declaration of test2
, so the IDE is offering to generate one.
绿色波浪线不会告诉您存在错误,而是告诉您新的重构工具有机会做一些事情。(红色波浪线表示错误。)在这种情况下,它们会通知您没有与 的声明匹配的定义test2
,因此 IDE 提供生成一个。
This happens to point out an error that was always there in the code, although Visual Studio might be behaving in a non-conforming manner.
这恰好指出了代码中始终存在的错误,尽管 Visual Studio 可能会以不符合规定的方式运行。
So what happens? The problem is that the declarations in the unnamed namespace do not declare the same functions that you later define in the global namespace. The refactoring tools recognize this and offer to generate a definition for the declared functions.
那么会发生什么?问题是未命名命名空间中的声明没有声明您稍后在全局命名空间中定义的相同函数。重构工具认识到这一点并提供为声明的函数生成定义。
However, the whole thing still compiles, due to the Microsoft compiler accepting two strictly illegal pieces of code. First, using the namespace prefix on the first declaration of a function is not allowed. The code in main
then presumably calls the functions. As Alex M showed in his answer, GCC won't accept this either, since the call is ambiguous. The Microsoft compiler appears to accept it, either treating the definition as a definition matching the declaration in the unnamed namespace (remember, the tools of the IDE, IntelliSense and the refactory, used the more compliant EDG front-end, not the parser the actual compiler uses, which means that the refactory can say that the declaration has no definition, while the compiler treats the definition as matching the declaration), or just preferring the global version to the namespaced version.
然而,整个事情仍然可以编译,因为微软编译器接受了两段严格非法的代码。首先,不允许在函数的第一个声明中使用命名空间前缀。代码在main
然后大概调用函数。正如亚历克斯 M 在他的回答中所示,海湾合作委员会也不会接受这一点,因为这个电话是模棱两可的。Microsoft 编译器似乎接受它,要么将定义视为与未命名命名空间中的声明匹配的定义(请记住,IDE、IntelliSense 和重构的工具使用了更兼容的 EDG 前端,而不是解析器实际编译器使用,这意味着重构可以说声明没有定义,而编译器将定义视为匹配声明),或者只是更喜欢全局版本而不是命名空间版本。
It's easy to distinguish the two cases, by the way. Rearrange the code so that main
comes before the function definitions. This will resolve the ambiguity in GCC, because only the namespaced function is declared (and not defined, so you should get a linker error). It will also lead to a linker error in the Microsoft compiler, if it just prefers the global version, but will still compile if it treats the declaration and definition as matching.
顺便说一下,很容易区分这两种情况。重新排列代码,使其main
位于函数定义之前。这将解决 GCC 中的歧义,因为只有命名空间函数被声明(而不是定义,所以你应该得到一个链接器错误)。如果它只是更喜欢全局版本,它也会导致 Microsoft 编译器中的链接器错误,但如果将声明和定义视为匹配,它仍然会编译。
The solution to all this is very simple: when defining functions declared in the unnamed namespace, just reopen the namespace instead of trying to define the functions outside.
解决这一切的方法很简单:在定义未命名命名空间中声明的函数时,只需重新打开命名空间,而不是尝试在外部定义函数。
回答by Sebastian Redl
This compiles OK, with the light bulb you mentioned:
用你提到的灯泡编译好:
namespace
{
void func();
}
void ::func() //Will not compile if 'void func()'
{}
int main()
{
func();
}
But IntelliSense also outputs (in both cases):
但 IntelliSense 也输出(在这两种情况下):
Error (active) more than one instance of overloaded function "func"
matches the argument list:
function "func()"
function "<unnamed>::func()"
Is this really what you want to do though? As n4527 at § 7.3.1.1 states:
这真的是你想做的吗?正如第 7.3.1.1 节中的 n4527 所述:
An unnamed-namespace-definitionbehaves as if it were replaced by
inline(opt) namespace unique { /* empty body */ } using namespace unique; namespace unique { namespace-body }
where inline appears if and only if it appears in the unnamed-namespace-definitionand all occurrences of unique in a translation unit are replaced by the same identifier, and this identifier differs from all other identifiers in the translation unit.
一个不愿透露姓名的命名空间定义,如果它被取代的行为
inline(opt) namespace unique { /* empty body */ } using namespace unique; namespace unique { namespace-body }
其中 inline 出现当且仅当它出现在 未命名命名空间定义中并且翻译单元中所有出现的 unique 都被相同的标识符替换,并且该标识符与翻译单元中的所有其他标识符不同。
Which makes it clear why there are ambiguities going on. Just define your methods withinyour unnamed namespace, as they're different from anything else outside it.
这清楚地说明了为什么会出现歧义。只需在未命名的命名空间中定义您的方法,因为它们与外部的任何其他方法都不同。
For the record, GCC 5.2.0 and clang 3.6.0 won't agree to compile the code that MSVC compiled.
作为记录,GCC 5.2.0 和 clang 3.6.0 不会同意编译 MSVC 编译的代码。